Refactor and cleanup a bunch of code
This commit is contained in:
parent
114fb723dc
commit
9cba544ffd
@ -39,7 +39,7 @@ import exh.eh.EHentaiThrottleManager
|
||||
import exh.metadata.metadata.base.getFlatMetadataForManga
|
||||
import exh.metadata.metadata.base.insertFlatMetadata
|
||||
import exh.savedsearches.JsonSavedSearch
|
||||
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
||||
import exh.source.getMainSource
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
|
@ -40,7 +40,7 @@ import exh.MERGED_SOURCE_ID
|
||||
import exh.md.utils.FollowStatus
|
||||
import exh.md.utils.MdUtil
|
||||
import exh.metadata.metadata.base.insertFlatMetadata
|
||||
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
||||
import exh.source.getMainSource
|
||||
import exh.util.asObservable
|
||||
import exh.util.await
|
||||
import exh.util.awaitSingle
|
||||
@ -425,7 +425,7 @@ class LibraryUpdateService(
|
||||
* @return a pair of the inserted and removed chapters.
|
||||
*/
|
||||
fun updateManga(manga: Manga): Observable<Pair<List<Chapter>, List<Chapter>>> {
|
||||
val source = sourceManager.getOrStub(manga.source)
|
||||
val source = sourceManager.getOrStub(manga.source).getMainSource()
|
||||
|
||||
// Update manga details metadata in the background
|
||||
if (preferences.autoUpdateMetadata()) {
|
||||
@ -447,8 +447,14 @@ class LibraryUpdateService(
|
||||
.subscribe()
|
||||
}
|
||||
|
||||
return (
|
||||
/* SY --> */ if (source is MergedSource) runBlocking { source.fetchChaptersAndSync(manga, false).asObservable() }
|
||||
else /* SY <-- */ source.fetchChapterList(manga)
|
||||
.map { syncChaptersWithSource(db, it, manga, source) }
|
||||
// SY -->
|
||||
if (source.getMainSource() is MangaDex && trackManager.mdList.isLogged) {
|
||||
)
|
||||
.doOnNext {
|
||||
if (source is MangaDex && trackManager.mdList.isLogged) {
|
||||
try {
|
||||
val tracks = db.getTracks(manga).executeAsBlocking()
|
||||
if (tracks.isEmpty() || tracks.all { it.sync_id != TrackManager.MDLIST }) {
|
||||
@ -460,23 +466,6 @@ class LibraryUpdateService(
|
||||
XLog.e(e)
|
||||
}
|
||||
}
|
||||
// SY <--
|
||||
|
||||
return (
|
||||
/* SY --> */ if (source is MergedSource) runBlocking { source.fetchChaptersAndSync(manga, false).asObservable() }
|
||||
else /* SY <-- */ source.fetchChapterList(manga)
|
||||
.map { syncChaptersWithSource(db, it, manga, source) }
|
||||
// SY -->
|
||||
)
|
||||
.doOnNext {
|
||||
if (source.getMainSource() is MangaDex) {
|
||||
val tracks = db.getTracks(manga).executeAsBlocking()
|
||||
if (tracks.isEmpty() || tracks.all { it.sync_id != TrackManager.MDLIST }) {
|
||||
var track = trackManager.mdList.createInitialTracker(manga)
|
||||
track = runBlocking { trackManager.mdList.refresh(track).awaitSingle() }
|
||||
db.insertTrack(track).executeAsBlocking()
|
||||
}
|
||||
}
|
||||
}
|
||||
// SY <--
|
||||
}
|
||||
@ -548,7 +537,7 @@ class LibraryUpdateService(
|
||||
// filter all follows from Mangadex and only add reading or rereading manga to library
|
||||
private fun syncFollows(): Observable<LibraryManga> {
|
||||
val count = AtomicInteger(0)
|
||||
val mangaDex = MdUtil.getEnabledMangaDex(preferences, sourceManager)!!
|
||||
val mangaDex = MdUtil.getEnabledMangaDex(preferences, sourceManager) ?: return Observable.empty()
|
||||
return mangaDex.fetchAllFollows(true)
|
||||
.asObservable()
|
||||
.map { listManga ->
|
||||
@ -582,7 +571,7 @@ class LibraryUpdateService(
|
||||
.doOnCompleted {
|
||||
notifier.cancelProgressNotification()
|
||||
}
|
||||
.map { LibraryManga() }
|
||||
.flatMap { Observable.empty() }
|
||||
}
|
||||
|
||||
/**
|
||||
@ -616,7 +605,7 @@ class LibraryUpdateService(
|
||||
.doOnCompleted {
|
||||
notifier.cancelProgressNotification()
|
||||
}
|
||||
.map { LibraryManga() }
|
||||
.flatMap { Observable.empty() }
|
||||
}
|
||||
// SY <--
|
||||
|
||||
|
@ -26,7 +26,7 @@ import exh.eh.EHTags
|
||||
import exh.eh.EHentaiUpdateHelper
|
||||
import exh.eh.EHentaiUpdateWorkerConstants
|
||||
import exh.eh.GalleryEntry
|
||||
import exh.metadata.EX_DATE_FORMAT
|
||||
import exh.metadata.MetadataUtil
|
||||
import exh.metadata.metadata.EHentaiSearchMetadata
|
||||
import exh.metadata.metadata.EHentaiSearchMetadata.Companion.EH_GENRE_NAMESPACE
|
||||
import exh.metadata.metadata.EHentaiSearchMetadata.Companion.TAG_TYPE_LIGHT
|
||||
@ -35,7 +35,6 @@ import exh.metadata.metadata.EHentaiSearchMetadata.Companion.TAG_TYPE_WEAK
|
||||
import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.TAG_TYPE_VIRTUAL
|
||||
import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.toGenreString
|
||||
import exh.metadata.metadata.base.RaisedTag
|
||||
import exh.metadata.parseHumanReadableByteCount
|
||||
import exh.ui.login.LoginController
|
||||
import exh.ui.metadata.adapters.EHentaiDescriptionAdapter
|
||||
import exh.util.UriFilter
|
||||
@ -239,7 +238,7 @@ class EHentai(
|
||||
private fun getDateTag(element: Element?): Long? {
|
||||
val text = element?.text()?.nullIfBlank()
|
||||
return if (text != null) {
|
||||
val date = EX_DATE_FORMAT.parse(text)
|
||||
val date = MetadataUtil.EX_DATE_FORMAT.parse(text)
|
||||
date?.time
|
||||
} else null
|
||||
}
|
||||
@ -272,8 +271,8 @@ class EHentai(
|
||||
/**
|
||||
* Parse a list of galleries
|
||||
*/
|
||||
fun genericMangaParse(response: Response) = extendedGenericMangaParse(response.asJsoup()).let {
|
||||
MetadataMangasPage(it.first.map { it.manga }, it.second, it.first.map { it.metadata })
|
||||
private fun genericMangaParse(response: Response) = extendedGenericMangaParse(response.asJsoup()).let { mangaFromSource ->
|
||||
MetadataMangasPage(mangaFromSource.first.map { it.manga }, mangaFromSource.second, mangaFromSource.first.map { it.metadata })
|
||||
}
|
||||
|
||||
override fun fetchChapterList(manga: SManga) = fetchChapterList(manga) {}
|
||||
@ -331,7 +330,7 @@ class EHentai(
|
||||
url = EHentaiSearchMetadata.normalizeUrl(d.location())
|
||||
name = "v1: " + d.selectFirst("#gn").text()
|
||||
chapter_number = 1f
|
||||
date_upload = EX_DATE_FORMAT.parse(
|
||||
date_upload = MetadataUtil.EX_DATE_FORMAT.parse(
|
||||
d.select("#gdd .gdt1").find { el ->
|
||||
el.text().toLowerCase() == "posted:"
|
||||
}!!.nextElementSibling().text()
|
||||
@ -348,7 +347,7 @@ class EHentai(
|
||||
this.url = EHentaiSearchMetadata.normalizeUrl(link)
|
||||
this.name = "v${index + 2}: $name"
|
||||
this.chapter_number = index + 2f
|
||||
this.date_upload = EX_DATE_FORMAT.parse(posted)!!.time
|
||||
this.date_upload = MetadataUtil.EX_DATE_FORMAT.parse(posted)!!.time
|
||||
}
|
||||
}.reversed() + self
|
||||
}
|
||||
@ -455,7 +454,7 @@ class EHentai(
|
||||
private fun exGet(url: String, page: Int? = null, additionalHeaders: Headers? = null, cache: Boolean = true): Request {
|
||||
return GET(
|
||||
page?.let {
|
||||
addParam(url, "page", Integer.toString(page - 1))
|
||||
addParam(url, "page", (page - 1).toString())
|
||||
} ?: url,
|
||||
additionalHeaders?.let { additionalHeadersNotNull ->
|
||||
val headers = headers.newBuilder()
|
||||
@ -524,39 +523,35 @@ class EHentai(
|
||||
override fun parseIntoMetadata(metadata: EHentaiSearchMetadata, input: Document) {
|
||||
with(metadata) {
|
||||
with(input) {
|
||||
val url = input.location()
|
||||
val url = location()
|
||||
gId = EHentaiSearchMetadata.galleryId(url)
|
||||
gToken = EHentaiSearchMetadata.galleryToken(url)
|
||||
|
||||
exh = this@EHentai.exh
|
||||
title = select("#gn").text().nullIfBlank()?.trim()
|
||||
title = select("#gn").text().trimOrNull()
|
||||
|
||||
altTitle = select("#gj").text().nullIfBlank()?.trim()
|
||||
altTitle = select("#gj").text().trimOrNull()
|
||||
|
||||
thumbnailUrl = select("#gd1 div").attr("style").nullIfBlank()?.let {
|
||||
it.substring(it.indexOf('(') + 1 until it.lastIndexOf(')'))
|
||||
}
|
||||
genre = select(".cs")
|
||||
.attr("onclick")
|
||||
.nullIfBlank()
|
||||
?.trim()
|
||||
.trimOrNull()
|
||||
?.substringAfterLast('/')
|
||||
?.removeSuffix("'")
|
||||
|
||||
uploader = select("#gdn").text().nullIfBlank()?.trim()
|
||||
uploader = select("#gdn").text().trimOrNull()
|
||||
|
||||
// Parse the table
|
||||
select("#gdd tr").forEach {
|
||||
val left = it.select(".gdt1").text().nullIfBlank()?.trim()
|
||||
val left = it.select(".gdt1").text().trimOrNull()
|
||||
val rightElement = it.selectFirst(".gdt2")
|
||||
val right = rightElement.text().nullIfBlank()?.trim()
|
||||
val right = rightElement.text().trimOrNull()
|
||||
if (left != null && right != null) {
|
||||
ignore {
|
||||
when (
|
||||
left.removeSuffix(":")
|
||||
.toLowerCase()
|
||||
) {
|
||||
"posted" -> datePosted = EX_DATE_FORMAT.parse(right)!!.time
|
||||
when (left.removeSuffix(":").toLowerCase()) {
|
||||
"posted" -> datePosted = MetadataUtil.EX_DATE_FORMAT.parse(right)!!.time
|
||||
// Example gallery with parent: https://e-hentai.org/g/1390451/7f181c2426/
|
||||
// Example JP gallery: https://exhentai.org/g/1375385/03519d541b/
|
||||
// Parent is older variation of the gallery
|
||||
@ -565,12 +560,12 @@ class EHentai(
|
||||
} else null
|
||||
"visible" -> visible = right.nullIfBlank()
|
||||
"language" -> {
|
||||
language = right.removeSuffix(TR_SUFFIX).trim().nullIfBlank()
|
||||
language = right.removeSuffix(TR_SUFFIX).trimOrNull()
|
||||
translated = right.endsWith(TR_SUFFIX, true)
|
||||
}
|
||||
"file size" -> size = parseHumanReadableByteCount(right)?.toLong()
|
||||
"length" -> length = right.removeSuffix("pages").trim().nullIfBlank()?.toInt()
|
||||
"favorited" -> favorites = right.removeSuffix("times").trim().nullIfBlank()?.toInt()
|
||||
"file size" -> size = MetadataUtil.parseHumanReadableByteCount(right)?.toLong()
|
||||
"length" -> length = right.removeSuffix("pages").trimOrNull()?.toInt()
|
||||
"favorited" -> favorites = right.removeSuffix("times").trimOrNull()?.toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -589,13 +584,11 @@ class EHentai(
|
||||
averageRating = select("#rating_label")
|
||||
.text()
|
||||
.removePrefix("Average:")
|
||||
.trim()
|
||||
.nullIfBlank()
|
||||
.trimOrNull()
|
||||
?.toDouble()
|
||||
ratingCount = select("#rating_count")
|
||||
.text()
|
||||
.trim()
|
||||
.nullIfBlank()
|
||||
.trimOrNull()
|
||||
?.toInt()
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ class NHentai(delegate: HttpSource, val context: Context) :
|
||||
tags.clear()
|
||||
}.forEach {
|
||||
if (it.first != null && it.second != null) {
|
||||
tags.add(RaisedTag(it.first!!, it.second!!, if (it.first == "category") RaisedSearchMetadata.TAG_TYPE_VIRTUAL else NHentaiSearchMetadata.TAG_TYPE_DEFAULT))
|
||||
tags.add(RaisedTag(it.first!!, it.second!!, if (it.first == NHentaiSearchMetadata.NHENTAI_CATEGORIES_NAMESPACE) RaisedSearchMetadata.TAG_TYPE_VIRTUAL else NHentaiSearchMetadata.TAG_TYPE_DEFAULT))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ import eu.kanade.tachiyomi.widget.EmptyView
|
||||
import exh.isEhBasedSource
|
||||
import exh.md.similar.ui.EnableMangaDexSimilarDialogController
|
||||
import exh.savedsearches.EXHSavedSearch
|
||||
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
||||
import exh.source.getMainSource
|
||||
import kotlinx.android.synthetic.main.main_activity.root_coordinator
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.drop
|
||||
|
@ -12,11 +12,10 @@ import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||
import eu.kanade.tachiyomi.data.glide.toMangaThumbnail
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import exh.metadata.EX_DATE_FORMAT
|
||||
import exh.metadata.MetadataUtil
|
||||
import exh.metadata.metadata.EHentaiSearchMetadata
|
||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||
import exh.util.SourceTagsUtil
|
||||
import exh.util.SourceTagsUtil.Companion.getLocaleSourceUtil
|
||||
import kotlinx.android.synthetic.main.source_enhanced_ehentai_list_item.date_posted
|
||||
import kotlinx.android.synthetic.main.source_enhanced_ehentai_list_item.genre
|
||||
import kotlinx.android.synthetic.main.source_enhanced_ehentai_list_item.language
|
||||
@ -82,11 +81,11 @@ class SourceEnhancedEHentaiListHolder(private val view: View, adapter: FlexibleA
|
||||
genre.text = view.context.getString(pair.second)
|
||||
} else genre.text = metadata.genre
|
||||
|
||||
metadata.datePosted?.let { date_posted.text = EX_DATE_FORMAT.format(Date(it)) }
|
||||
metadata.datePosted?.let { date_posted.text = MetadataUtil.EX_DATE_FORMAT.format(Date(it)) }
|
||||
|
||||
metadata.averageRating?.let { rating_bar.rating = it.toFloat() }
|
||||
|
||||
val locale = getLocaleSourceUtil(metadata.tags.firstOrNull { it.namespace == "language" }?.name)
|
||||
val locale = SourceTagsUtil.getLocaleSourceUtil(metadata.tags.firstOrNull { it.namespace == "language" }?.name)
|
||||
val pageCount = metadata.length
|
||||
|
||||
language.text = if (locale != null && pageCount != null) {
|
||||
|
@ -19,7 +19,7 @@ import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.source.online.BrowseSourceFilterHeader
|
||||
import eu.kanade.tachiyomi.widget.SimpleNavigationView
|
||||
import exh.savedsearches.EXHSavedSearch
|
||||
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
||||
import exh.source.getMainSource
|
||||
|
||||
class SourceFilterSheet(
|
||||
activity: Activity,
|
||||
|
@ -21,10 +21,9 @@ import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.online.NamespaceSource
|
||||
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
|
||||
import exh.metadata.metadata.base.RaisedTag
|
||||
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
||||
import exh.util.SourceTagsUtil.Companion.TAG_TYPE_EXCLUDE
|
||||
import exh.util.SourceTagsUtil.Companion.getRaisedTags
|
||||
import exh.util.SourceTagsUtil.Companion.parseTag
|
||||
import exh.source.getMainSource
|
||||
import exh.util.SourceTagsUtil
|
||||
import exh.util.getRaisedTags
|
||||
import kotlinx.android.synthetic.main.source_compact_grid_item.view.card
|
||||
import kotlinx.android.synthetic.main.source_compact_grid_item.view.gradient
|
||||
import uy.kohesive.injekt.Injekt
|
||||
@ -160,14 +159,14 @@ class LibraryItem(val manga: LibraryManga, private val libraryDisplayMode: Prefe
|
||||
}
|
||||
cleanConstraint.split(",").all {
|
||||
if (raisedTags == null) containsGenre(it.trim(), genres) else containsRaisedGenre(
|
||||
parseTag(it.trim()),
|
||||
SourceTagsUtil.parseTag(it.trim()),
|
||||
raisedTags
|
||||
)
|
||||
}
|
||||
} else if (raisedTags == null) {
|
||||
containsGenre(constraint, genres)
|
||||
} else {
|
||||
containsRaisedGenre(parseTag(constraint), raisedTags)
|
||||
containsRaisedGenre(SourceTagsUtil.parseTag(constraint), raisedTags)
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,7 +174,7 @@ class LibraryItem(val manga: LibraryManga, private val libraryDisplayMode: Prefe
|
||||
val genre = genres.find {
|
||||
(it.namespace?.toLowerCase() == tag.namespace?.toLowerCase() && it.name.toLowerCase() == tag.name.toLowerCase())
|
||||
}
|
||||
return if (tag.type == TAG_TYPE_EXCLUDE) {
|
||||
return if (tag.type == SourceTagsUtil.TAG_TYPE_EXCLUDE) {
|
||||
genre == null
|
||||
} else {
|
||||
genre != null
|
||||
|
@ -103,7 +103,7 @@ import exh.isEhBasedSource
|
||||
import exh.md.similar.ui.MangaDexSimilarController
|
||||
import exh.metadata.metadata.base.FlatMetadata
|
||||
import exh.recs.RecommendsController
|
||||
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
||||
import exh.source.getMainSource
|
||||
import kotlinx.android.synthetic.main.main_activity.root_coordinator
|
||||
import kotlinx.android.synthetic.main.main_activity.toolbar
|
||||
import kotlinx.coroutines.CancellationException
|
||||
|
@ -50,7 +50,7 @@ import exh.metadata.metadata.base.FlatMetadata
|
||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||
import exh.metadata.metadata.base.getFlatMetadataForManga
|
||||
import exh.metadata.metadata.base.insertFlatMetadata
|
||||
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
||||
import exh.source.getMainSource
|
||||
import exh.util.asObservable
|
||||
import exh.util.await
|
||||
import exh.util.shouldDeleteChapters
|
||||
|
@ -11,7 +11,7 @@ import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
||||
import exh.EH_SOURCE_ID
|
||||
import exh.EXH_SOURCE_ID
|
||||
import exh.metadata.EX_DATE_FORMAT
|
||||
import exh.metadata.MetadataUtil
|
||||
import kotlinx.android.synthetic.main.chapters_item.bookmark_icon
|
||||
import kotlinx.android.synthetic.main.chapters_item.chapter_description
|
||||
import kotlinx.android.synthetic.main.chapters_item.chapter_title
|
||||
@ -56,7 +56,7 @@ class ChapterHolder(
|
||||
if (chapter.date_upload > 0) {
|
||||
// SY -->
|
||||
if (manga.source == EH_SOURCE_ID || manga.source == EXH_SOURCE_ID) {
|
||||
descriptions.add(EX_DATE_FORMAT.format(Date(chapter.date_upload)))
|
||||
descriptions.add(MetadataUtil.EX_DATE_FORMAT.format(Date(chapter.date_upload)))
|
||||
} else /* SY <-- */ descriptions.add(adapter.dateFormat.format(Date(chapter.date_upload)))
|
||||
}
|
||||
if ((!chapter.read || (adapter.preserveReadingPosition && (manga.source == EH_SOURCE_ID || manga.source == EXH_SOURCE_ID))) && chapter.last_page_read > 0) {
|
||||
|
@ -18,7 +18,7 @@ import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Stat
|
||||
import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog
|
||||
import exh.md.utils.MdUtil
|
||||
import exh.metadata.metadata.MangaDexSearchMetadata
|
||||
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
||||
import exh.source.getMainSource
|
||||
|
||||
class ChaptersSettingsSheet(
|
||||
private val router: Router,
|
||||
|
@ -22,7 +22,7 @@ import eu.kanade.tachiyomi.source.online.all.MangaDex
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import exh.MERGED_SOURCE_ID
|
||||
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
||||
import exh.source.getMainSource
|
||||
import exh.util.SourceTagsUtil
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@ -107,7 +107,7 @@ class MangaInfoHeaderAdapter(
|
||||
|
||||
with(binding.btnTracking) {
|
||||
// SY -->
|
||||
val sourceIsMangaDex = source.let { it.getMainSource() is MangaDex }
|
||||
val sourceIsMangaDex = source.getMainSource() is MangaDex
|
||||
// SY <--
|
||||
if (trackManager.hasLoggedServices(/* SY --> */sourceIsMangaDex/* SY <-- */)) {
|
||||
isVisible = true
|
||||
@ -169,7 +169,7 @@ class MangaInfoHeaderAdapter(
|
||||
val author = binding.mangaAuthor.text.toString()
|
||||
controller.activity?.copyToClipboard(
|
||||
author,
|
||||
SourceTagsUtil().getWrappedTag(source.id, namespace = "artist", tag = author) ?: author
|
||||
SourceTagsUtil.getWrappedTag(source.id, namespace = "artist", tag = author) ?: author
|
||||
)
|
||||
// SY <--
|
||||
}
|
||||
@ -179,7 +179,7 @@ class MangaInfoHeaderAdapter(
|
||||
.onEach {
|
||||
// SY -->
|
||||
val author = binding.mangaAuthor.text.toString()
|
||||
controller.performGlobalSearch(SourceTagsUtil().getWrappedTag(source.id, namespace = "artist", tag = author) ?: author)
|
||||
controller.performGlobalSearch(SourceTagsUtil.getWrappedTag(source.id, namespace = "artist", tag = author) ?: author)
|
||||
// SY <--
|
||||
}
|
||||
.launchIn(scope)
|
||||
@ -190,7 +190,7 @@ class MangaInfoHeaderAdapter(
|
||||
val artist = binding.mangaArtist.text.toString()
|
||||
controller.activity?.copyToClipboard(
|
||||
artist,
|
||||
SourceTagsUtil().getWrappedTag(source.id, namespace = "artist", tag = artist) ?: artist
|
||||
SourceTagsUtil.getWrappedTag(source.id, namespace = "artist", tag = artist) ?: artist
|
||||
)
|
||||
// SY <--
|
||||
}
|
||||
@ -200,7 +200,7 @@ class MangaInfoHeaderAdapter(
|
||||
.onEach {
|
||||
// SY -->
|
||||
val artist = binding.mangaArtist.text.toString()
|
||||
controller.performGlobalSearch(SourceTagsUtil().getWrappedTag(source.id, namespace = "artist", tag = artist) ?: artist)
|
||||
controller.performGlobalSearch(SourceTagsUtil.getWrappedTag(source.id, namespace = "artist", tag = artist) ?: artist)
|
||||
// SY <--
|
||||
}
|
||||
.launchIn(scope)
|
||||
|
@ -20,8 +20,8 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import exh.isEhBasedSource
|
||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||
import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.TAG_TYPE_VIRTUAL
|
||||
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
||||
import exh.util.SourceTagsUtil.Companion.getRaisedTags
|
||||
import exh.source.getMainSource
|
||||
import exh.util.getRaisedTags
|
||||
import exh.util.makeSearchChip
|
||||
import exh.util.setChipsExtended
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
@ -40,7 +40,7 @@ import exh.md.utils.MdUtil
|
||||
import exh.md.utils.scanlatorList
|
||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||
import exh.metadata.metadata.base.getFlatMetadataForManga
|
||||
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
||||
import exh.source.getMainSource
|
||||
import exh.util.awaitSingleOrNull
|
||||
import exh.util.defaultReaderType
|
||||
import exh.util.shouldDeleteChapters
|
||||
|
@ -34,12 +34,12 @@ class SettingsMangaDexController :
|
||||
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
|
||||
titleRes = R.string.mangadex_specific_settings
|
||||
if (mdex == null) return@apply
|
||||
val sourcePreference = MangaDexLoginPreference(context, mdex!!).apply {
|
||||
title = mdex!!.name + " Login"
|
||||
val mdex = mdex ?: return@apply
|
||||
val sourcePreference = MangaDexLoginPreference(context, mdex).apply {
|
||||
title = mdex.name + " Login"
|
||||
key = getSourceKey(source.id)
|
||||
setOnLoginClickListener {
|
||||
if (mdex!!.isLogged()) {
|
||||
if (mdex.isLogged()) {
|
||||
val dialog = MangadexLogoutDialog(source)
|
||||
dialog.targetController = this@SettingsMangaDexController
|
||||
dialog.showDialog(router)
|
||||
|
@ -10,7 +10,7 @@ import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
||||
import eu.kanade.tachiyomi.source.online.all.EHentai
|
||||
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
|
||||
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
||||
import exh.source.getMainSource
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.util.Date
|
||||
|
||||
|
@ -8,7 +8,6 @@ import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.SourceManager.Companion.currentDelegatedSources
|
||||
import exh.EH_SOURCE_ID
|
||||
import exh.EXHMigrations
|
||||
import exh.EXH_SOURCE_ID
|
||||
@ -69,7 +68,7 @@ object DebugFunctions {
|
||||
}
|
||||
private val throttleManager = EHentaiThrottleManager()
|
||||
|
||||
fun getDelegatedSourceList(): String = currentDelegatedSources.map { it.value.sourceName + " : " + it.value.sourceId + " : " + it.value.factory }.joinToString(separator = "\n")
|
||||
fun getDelegatedSourceList(): String = SourceManager.currentDelegatedSources.map { it.value.sourceName + " : " + it.value.sourceId + " : " + it.value.factory }.joinToString(separator = "\n")
|
||||
|
||||
fun resetEHGalleriesForUpdater() {
|
||||
throttleManager.resetThrottle()
|
||||
|
@ -4,7 +4,7 @@ import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.source.online.all.MangaDex
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.Pager
|
||||
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
||||
import exh.source.getMainSource
|
||||
|
||||
/**
|
||||
* Presenter of [MangaDexFollowsController]. Inherit BrowseCataloguePresenter.
|
||||
|
@ -15,6 +15,7 @@ import exh.metadata.metadata.base.RaisedTag
|
||||
import exh.metadata.metadata.base.getFlatMetadataForManga
|
||||
import exh.metadata.metadata.base.insertFlatMetadata
|
||||
import exh.util.floor
|
||||
import exh.util.nullIfZero
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
@ -126,7 +127,7 @@ class ApiMangaParser(private val langs: List<String>) {
|
||||
genres.add("Hentai")
|
||||
}
|
||||
|
||||
if (tags.size != 0) tags.clear()
|
||||
if (tags.isNotEmpty()) tags.clear()
|
||||
tags += genres.map { RaisedTag(null, it, MangaDexSearchMetadata.TAG_TYPE_DEFAULT) }
|
||||
} catch (e: Exception) {
|
||||
XLog.e(e)
|
||||
@ -157,10 +158,8 @@ class ApiMangaParser(private val langs: List<String>) {
|
||||
}
|
||||
}
|
||||
val removeOneshots = filteredChapters.asSequence()
|
||||
.map { it.value.chapter!!.toDoubleOrNull() }
|
||||
.filter { it != null }
|
||||
.map { it!!.floor() }
|
||||
.filter { it != 0 }
|
||||
.map { it.value.chapter?.toDoubleOrNull()?.floor()?.nullIfZero() }
|
||||
.filterNotNull()
|
||||
.toList().distinctBy { it }
|
||||
return removeOneshots.toList().size == finalChapterNumber.toDouble().floor()
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.network.asObservable
|
||||
import eu.kanade.tachiyomi.network.await
|
||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
import eu.kanade.tachiyomi.source.model.MetadataMangasPage
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
@ -14,8 +15,6 @@ import exh.md.handlers.serializers.FollowsPageResult
|
||||
import exh.md.handlers.serializers.Result
|
||||
import exh.md.utils.FollowStatus
|
||||
import exh.md.utils.MdUtil
|
||||
import exh.md.utils.MdUtil.Companion.baseUrl
|
||||
import exh.md.utils.MdUtil.Companion.getMangaId
|
||||
import exh.metadata.metadata.MangaDexSearchMetadata
|
||||
import exh.util.floor
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@ -101,7 +100,7 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers, val prefere
|
||||
if (result[0].chapter.isNotBlank()) {
|
||||
track.last_chapter_read = follow.chapter.toFloat().floor()
|
||||
}
|
||||
track.tracking_url = baseUrl + follow.manga_id.toString()
|
||||
track.tracking_url = MdUtil.baseUrl + follow.manga_id.toString()
|
||||
track.title = follow.title
|
||||
}
|
||||
return track
|
||||
@ -111,7 +110,7 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers, val prefere
|
||||
*
|
||||
*/
|
||||
private fun followsListRequest(): Request {
|
||||
return GET("$baseUrl${MdUtil.followsAllApi}", headers, CacheControl.FORCE_NETWORK)
|
||||
return GET("${MdUtil.baseUrl}${MdUtil.followsAllApi}", headers, CacheControl.FORCE_NETWORK)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,66 +138,66 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers, val prefere
|
||||
if (followStatus == FollowStatus.UNFOLLOWED) {
|
||||
client.newCall(
|
||||
GET(
|
||||
"$baseUrl/ajax/actions.ajax.php?function=manga_unfollow&id=$mangaID&type=$mangaID",
|
||||
"${MdUtil.baseUrl}/ajax/actions.ajax.php?function=manga_unfollow&id=$mangaID&type=$mangaID",
|
||||
headers,
|
||||
CacheControl.FORCE_NETWORK
|
||||
)
|
||||
)
|
||||
.execute()
|
||||
.await()
|
||||
} else {
|
||||
val status = followStatus.int
|
||||
client.newCall(
|
||||
GET(
|
||||
"$baseUrl/ajax/actions.ajax.php?function=manga_follow&id=$mangaID&type=$status",
|
||||
"${MdUtil.baseUrl}/ajax/actions.ajax.php?function=manga_follow&id=$mangaID&type=$status",
|
||||
headers,
|
||||
CacheControl.FORCE_NETWORK
|
||||
)
|
||||
)
|
||||
.execute()
|
||||
.await()
|
||||
}
|
||||
|
||||
response.body!!.string().isEmpty()
|
||||
withContext(Dispatchers.IO) { response.body!!.string().isEmpty() }
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun updateReadingProgress(track: Track): Boolean {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val mangaID = getMangaId(track.tracking_url)
|
||||
val mangaID = MdUtil.getMangaId(track.tracking_url)
|
||||
val formBody = FormBody.Builder()
|
||||
.add("chapter", track.last_chapter_read.toString())
|
||||
XLog.d("chapter to update %s", track.last_chapter_read.toString())
|
||||
val response = client.newCall(
|
||||
POST(
|
||||
"$baseUrl/ajax/actions.ajax.php?function=edit_progress&id=$mangaID",
|
||||
"${MdUtil.baseUrl}/ajax/actions.ajax.php?function=edit_progress&id=$mangaID",
|
||||
headers,
|
||||
formBody.build()
|
||||
)
|
||||
).execute()
|
||||
).await()
|
||||
|
||||
val response2 = client.newCall(
|
||||
client.newCall(
|
||||
GET(
|
||||
"$baseUrl/ajax/actions.ajax.php?function=manga_rating&id=$mangaID&rating=${track.score.toInt()}",
|
||||
"${MdUtil.baseUrl}/ajax/actions.ajax.php?function=manga_rating&id=$mangaID&rating=${track.score.toInt()}",
|
||||
headers
|
||||
)
|
||||
)
|
||||
.execute()
|
||||
.await()
|
||||
|
||||
response.body!!.string().isEmpty()
|
||||
withContext(Dispatchers.IO) { response.body!!.string().isEmpty() }
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun updateRating(track: Track): Boolean {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val mangaID = getMangaId(track.tracking_url)
|
||||
val mangaID = MdUtil.getMangaId(track.tracking_url)
|
||||
val response = client.newCall(
|
||||
GET(
|
||||
"$baseUrl/ajax/actions.ajax.php?function=manga_rating&id=$mangaID&rating=${track.score.toInt()}",
|
||||
"${MdUtil.baseUrl}/ajax/actions.ajax.php?function=manga_rating&id=$mangaID&rating=${track.score.toInt()}",
|
||||
headers
|
||||
)
|
||||
)
|
||||
.execute()
|
||||
.await()
|
||||
|
||||
response.body!!.string().isEmpty()
|
||||
withContext(Dispatchers.IO) { response.body!!.string().isEmpty() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,7 +207,7 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers, val prefere
|
||||
suspend fun fetchAllFollows(forceHd: Boolean): List<Pair<SManga, MangaDexSearchMetadata>> {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val listManga = mutableListOf<Pair<SManga, MangaDexSearchMetadata>>()
|
||||
val response = client.newCall(followsListRequest()).execute()
|
||||
val response = client.newCall(followsListRequest()).await()
|
||||
val mangasPage = followsParseMangaPage(response, forceHd)
|
||||
listManga.addAll(
|
||||
mangasPage.mangas.mapIndexed { index, sManga ->
|
||||
@ -222,11 +221,11 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers, val prefere
|
||||
suspend fun fetchTrackingInfo(url: String): Track {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val request = GET(
|
||||
"$baseUrl${MdUtil.followsMangaApi}" + getMangaId(url),
|
||||
"${MdUtil.baseUrl}${MdUtil.followsMangaApi}" + MdUtil.getMangaId(url),
|
||||
headers,
|
||||
CacheControl.FORCE_NETWORK
|
||||
)
|
||||
val response = client.newCall(request).execute()
|
||||
val response = client.newCall(request).await()
|
||||
val track = followStatusParse(response)
|
||||
|
||||
track
|
||||
|
@ -22,10 +22,10 @@ class MangaHandler(val client: OkHttpClient, val headers: Headers, val langs: Li
|
||||
// TODO make use of this
|
||||
suspend fun fetchMangaAndChapterDetails(manga: SManga): Pair<SManga, List<SChapter>> {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val response = client.newCall(apiRequest(manga)).execute()
|
||||
val response = client.newCall(apiRequest(manga)).await()
|
||||
val parser = ApiMangaParser(langs)
|
||||
|
||||
val jsonData = response.body!!.string()
|
||||
val jsonData = withContext(Dispatchers.IO) { response.body!!.string() }
|
||||
if (response.code != 200) {
|
||||
XLog.e("error from MangaDex with response code ${response.code} \n body: \n$jsonData")
|
||||
throw Exception("Error from MangaDex Response code ${response.code} ")
|
||||
@ -43,14 +43,14 @@ class MangaHandler(val client: OkHttpClient, val headers: Headers, val langs: Li
|
||||
suspend fun getMangaIdFromChapterId(urlChapterId: String): Int {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val request = GET(MdUtil.baseUrl + MdUtil.apiChapter + urlChapterId + MdUtil.apiChapterSuffix, headers, CacheControl.FORCE_NETWORK)
|
||||
val response = client.newCall(request).execute()
|
||||
val response = client.newCall(request).await()
|
||||
ApiMangaParser(langs).chapterParseForMangaId(response)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun fetchMangaDetails(manga: SManga): SManga {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val response = client.newCall(apiRequest(manga)).execute()
|
||||
val response = client.newCall(apiRequest(manga)).await()
|
||||
ApiMangaParser(langs).parseToManga(manga, response, forceLatestCovers).await()
|
||||
manga.apply {
|
||||
initialized = true
|
||||
@ -82,7 +82,7 @@ class MangaHandler(val client: OkHttpClient, val headers: Headers, val langs: Li
|
||||
|
||||
suspend fun fetchChapterList(manga: SManga): List<SChapter> {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val response = client.newCall(apiRequest(manga)).execute()
|
||||
val response = client.newCall(apiRequest(manga)).await()
|
||||
ApiMangaParser(langs).chapterListParse(response)
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.source.online.all.MangaDex
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.Pager
|
||||
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
||||
import exh.source.getMainSource
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
/**
|
||||
|
@ -6,7 +6,9 @@ import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.all.MangaDex
|
||||
import exh.source.getMainSource
|
||||
import exh.util.floor
|
||||
import exh.util.nullIfZero
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.jsoup.parser.Parser
|
||||
import uy.kohesive.injekt.Injekt
|
||||
@ -14,6 +16,7 @@ import uy.kohesive.injekt.api.get
|
||||
import java.net.URI
|
||||
import java.net.URISyntaxException
|
||||
|
||||
@Suppress("unused")
|
||||
class MdUtil {
|
||||
|
||||
companion object {
|
||||
@ -201,8 +204,8 @@ class MdUtil {
|
||||
/*}*/
|
||||
}.sortedByDescending { it.chapter_number }
|
||||
|
||||
remove0ChaptersFromCount.firstOrNull()?.let {
|
||||
val chpNumber = it.chapter_number.floor()
|
||||
remove0ChaptersFromCount.firstOrNull()?.let { chapter ->
|
||||
val chpNumber = chapter.chapter_number.floor()
|
||||
val allChapters = (1..chpNumber).toMutableSet()
|
||||
|
||||
remove0ChaptersFromCount.forEach {
|
||||
@ -217,8 +220,9 @@ class MdUtil {
|
||||
|
||||
fun getEnabledMangaDex(preferences: PreferencesHelper = Injekt.get(), sourceManager: SourceManager = Injekt.get()): MangaDex? {
|
||||
return getEnabledMangaDexs(preferences, sourceManager).let { mangadexs ->
|
||||
val preferredMangaDexId = preferences.preferredMangaDexId().get().toLongOrNull()
|
||||
mangadexs.firstOrNull { preferredMangaDexId != null && preferredMangaDexId != 0L && it.id == preferredMangaDexId } ?: mangadexs.firstOrNull()
|
||||
preferences.preferredMangaDexId().get().toLongOrNull()?.nullIfZero()?.let { preferredMangaDexId ->
|
||||
mangadexs.firstOrNull { it.id == preferredMangaDexId }
|
||||
} ?: mangadexs.firstOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,10 +230,11 @@ class MdUtil {
|
||||
val languages = preferences.enabledLanguages().get()
|
||||
val disabledSourceIds = preferences.disabledSources().get()
|
||||
|
||||
return sourceManager.getDelegatedCatalogueSources()
|
||||
return sourceManager.getVisibleOnlineSources()
|
||||
.map { it.getMainSource() }
|
||||
.filterIsInstance<MangaDex>()
|
||||
.filter { it.lang in languages }
|
||||
.filterNot { it.id.toString() in disabledSourceIds }
|
||||
.filterIsInstance(MangaDex::class.java)
|
||||
}
|
||||
|
||||
fun mapMdIdToMangaUrl(id: Int) = "/manga/$id/"
|
||||
|
@ -1,13 +1,25 @@
|
||||
package exh.metadata
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.FloatRange
|
||||
import androidx.core.content.ContextCompat
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import exh.util.SourceTagsUtil
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import kotlin.math.ln
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* Metadata utils
|
||||
*/
|
||||
object MetadataUtil {
|
||||
fun humanReadableByteCount(bytes: Long, si: Boolean): String {
|
||||
val unit = if (si) 1000 else 1024
|
||||
if (bytes < unit) return "$bytes B"
|
||||
@ -37,10 +49,6 @@ fun parseHumanReadableByteCount(arg0: String): Double? {
|
||||
return null
|
||||
}
|
||||
|
||||
fun <K, V> Set<Map.Entry<K, V>>.forEach(action: (K, V) -> Unit) {
|
||||
forEach { action(it.key, it.value) }
|
||||
}
|
||||
|
||||
val ONGOING_SUFFIX = arrayOf(
|
||||
"[ongoing]",
|
||||
"(ongoing)",
|
||||
@ -60,3 +68,51 @@ val ONGOING_SUFFIX = arrayOf(
|
||||
)
|
||||
|
||||
val EX_DATE_FORMAT = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US)
|
||||
|
||||
fun getRatingString(context: Context, @FloatRange(from = 0.0, to = 10.0) rating: Float?) = when ((rating ?: 100F).roundToInt()) {
|
||||
0 -> R.string.rating0
|
||||
1 -> R.string.rating1
|
||||
2 -> R.string.rating2
|
||||
3 -> R.string.rating3
|
||||
4 -> R.string.rating4
|
||||
5 -> R.string.rating5
|
||||
6 -> R.string.rating6
|
||||
7 -> R.string.rating7
|
||||
8 -> R.string.rating8
|
||||
9 -> R.string.rating9
|
||||
10 -> R.string.rating10
|
||||
else -> R.string.no_rating
|
||||
}.let { context.getString(it) }
|
||||
|
||||
fun getGenreAndColour(context: Context, genre: String) = when (genre) {
|
||||
"doujinshi", "Doujinshi" -> SourceTagsUtil.DOUJINSHI_COLOR to R.string.doujinshi
|
||||
"manga", "Japanese Manga", "Manga" -> SourceTagsUtil.MANGA_COLOR to R.string.manga
|
||||
"artistcg", "artist CG", "artist-cg", "Artist CG" -> SourceTagsUtil.ARTIST_CG_COLOR to R.string.artist_cg
|
||||
"gamecg", "game CG", "game-cg", "Game CG" -> SourceTagsUtil.GAME_CG_COLOR to R.string.game_cg
|
||||
"western" -> SourceTagsUtil.WESTERN_COLOR to R.string.western
|
||||
"non-h", "non-H" -> SourceTagsUtil.NON_H_COLOR to R.string.non_h
|
||||
"imageset", "image Set" -> SourceTagsUtil.IMAGE_SET_COLOR to R.string.image_set
|
||||
"cosplay" -> SourceTagsUtil.COSPLAY_COLOR to R.string.cosplay
|
||||
"asianporn", "asian Porn" -> SourceTagsUtil.ASIAN_PORN_COLOR to R.string.asian_porn
|
||||
"misc" -> SourceTagsUtil.MISC_COLOR to R.string.misc
|
||||
"Korean Manhwa" -> SourceTagsUtil.ARTIST_CG_COLOR to R.string.manhwa
|
||||
"Chinese Manhua" -> SourceTagsUtil.GAME_CG_COLOR to R.string.manhua
|
||||
"Comic" -> SourceTagsUtil.WESTERN_COLOR to R.string.comic
|
||||
"artbook" -> SourceTagsUtil.IMAGE_SET_COLOR to R.string.artbook
|
||||
"webtoon" -> SourceTagsUtil.NON_H_COLOR to R.string.webtoon
|
||||
"Video" -> SourceTagsUtil.WESTERN_COLOR to R.string.video
|
||||
else -> "" to 0
|
||||
}.let { if (it.second == 0) null else Color.parseColor(it.first) to context.getString(it.second) }
|
||||
}
|
||||
|
||||
fun <K, V> Set<Map.Entry<K, V>>.forEach(action: (K, V) -> Unit) {
|
||||
forEach { action(it.key, it.value) }
|
||||
}
|
||||
|
||||
fun TextView.bindDrawable(context: Context, @DrawableRes drawable: Int) {
|
||||
ContextCompat.getDrawable(context, drawable)?.apply {
|
||||
setTint(context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,7 @@ import android.net.Uri
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import exh.metadata.EX_DATE_FORMAT
|
||||
import exh.metadata.ONGOING_SUFFIX
|
||||
import exh.metadata.humanReadableByteCount
|
||||
import exh.metadata.MetadataUtil
|
||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||
import kotlinx.serialization.Serializable
|
||||
import uy.kohesive.injekt.Injekt
|
||||
@ -71,7 +69,7 @@ class EHentaiSearchMetadata : RaisedSearchMetadata() {
|
||||
// We default to completed
|
||||
manga.status = SManga.COMPLETED
|
||||
title?.let { t ->
|
||||
ONGOING_SUFFIX.find {
|
||||
MetadataUtil.ONGOING_SUFFIX.find {
|
||||
t.endsWith(it, ignoreCase = true)
|
||||
}?.let {
|
||||
manga.status = SManga.ONGOING
|
||||
@ -111,25 +109,26 @@ class EHentaiSearchMetadata : RaisedSearchMetadata() {
|
||||
|
||||
override fun getExtraInfoPairs(context: Context): List<Pair<String, String>> {
|
||||
val pairs = mutableListOf<Pair<String, String>>()
|
||||
gId?.let { pairs += Pair(context.getString(R.string.id), it) }
|
||||
gToken?.let { pairs += Pair(context.getString(R.string.token), it) }
|
||||
exh?.let { pairs += Pair(context.getString(R.string.is_exhentai_gallery), context.getString(if (it) android.R.string.yes else android.R.string.no)) }
|
||||
thumbnailUrl?.let { pairs += Pair(context.getString(R.string.thumbnail_url), it) }
|
||||
title?.let { pairs += Pair(context.getString(R.string.title), it) }
|
||||
altTitle?.let { pairs += Pair(context.getString(R.string.alt_title), it) }
|
||||
genre?.let { pairs += Pair(context.getString(R.string.genre), it) }
|
||||
datePosted?.let { pairs += Pair(context.getString(R.string.date_posted), EX_DATE_FORMAT.format(Date(it))) }
|
||||
parent?.let { pairs += Pair(context.getString(R.string.parent), it) }
|
||||
visible?.let { pairs += Pair(context.getString(R.string.visible), it) }
|
||||
language?.let { pairs += Pair(context.getString(R.string.language), it) }
|
||||
translated?.let { pairs += Pair("Translated", context.getString(if (it) android.R.string.yes else android.R.string.no)) }
|
||||
size?.let { pairs += Pair(context.getString(R.string.gallery_size), humanReadableByteCount(it, true)) }
|
||||
length?.let { pairs += Pair(context.getString(R.string.page_count), it.toString()) }
|
||||
favorites?.let { pairs += Pair(context.getString(R.string.total_favorites), it.toString()) }
|
||||
ratingCount?.let { pairs += Pair(context.getString(R.string.total_ratings), it.toString()) }
|
||||
averageRating?.let { pairs += Pair(context.getString(R.string.average_rating), it.toString()) }
|
||||
aged.let { pairs += Pair(context.getString(R.string.aged), context.getString(if (it) android.R.string.yes else android.R.string.no)) }
|
||||
lastUpdateCheck.let { pairs += Pair(context.getString(R.string.last_update_check), EX_DATE_FORMAT.format(Date(it))) }
|
||||
|
||||
gId?.let { pairs += context.getString(R.string.id) to it }
|
||||
gToken?.let { pairs += context.getString(R.string.token) to it }
|
||||
exh?.let { pairs += context.getString(R.string.is_exhentai_gallery) to context.getString(if (it) android.R.string.yes else android.R.string.no) }
|
||||
thumbnailUrl?.let { pairs += context.getString(R.string.thumbnail_url) to it }
|
||||
title?.let { pairs += context.getString(R.string.title) to it }
|
||||
altTitle?.let { pairs += context.getString(R.string.alt_title) to it }
|
||||
genre?.let { pairs += context.getString(R.string.genre) to it }
|
||||
datePosted?.let { pairs += context.getString(R.string.date_posted) to MetadataUtil.EX_DATE_FORMAT.format(Date(it)) }
|
||||
parent?.let { pairs += context.getString(R.string.parent) to it }
|
||||
visible?.let { pairs += context.getString(R.string.visible) to it }
|
||||
language?.let { pairs += context.getString(R.string.language) to it }
|
||||
translated?.let { pairs += "Translated" to context.getString(if (it) android.R.string.yes else android.R.string.no) }
|
||||
size?.let { pairs += context.getString(R.string.gallery_size) to MetadataUtil.humanReadableByteCount(it, true) }
|
||||
length?.let { pairs += context.getString(R.string.page_count) to it.toString() }
|
||||
favorites?.let { pairs += context.getString(R.string.total_favorites) to it.toString() }
|
||||
ratingCount?.let { pairs += context.getString(R.string.total_ratings) to it.toString() }
|
||||
averageRating?.let { pairs += context.getString(R.string.average_rating) to it.toString() }
|
||||
aged.let { pairs += context.getString(R.string.aged) to context.getString(if (it) android.R.string.yes else android.R.string.no) }
|
||||
lastUpdateCheck.let { pairs += context.getString(R.string.last_update_check) to MetadataUtil.EX_DATE_FORMAT.format(Date(it)) }
|
||||
|
||||
return pairs
|
||||
}
|
||||
|
@ -41,12 +41,12 @@ class EightMusesSearchMetadata : RaisedSearchMetadata() {
|
||||
|
||||
override fun getExtraInfoPairs(context: Context): List<Pair<String, String>> {
|
||||
val pairs = mutableListOf<Pair<String, String>>()
|
||||
title?.let { pairs += Pair(context.getString(R.string.title), it) }
|
||||
title?.let { pairs += context.getString(R.string.title) to it }
|
||||
val path = path.joinToString("/", prefix = "/")
|
||||
if (path.isNotBlank()) {
|
||||
pairs += Pair(context.getString(R.string.path), path)
|
||||
pairs += context.getString(R.string.path) to path
|
||||
}
|
||||
thumbnailUrl?.let { pairs += Pair(context.getString(R.string.thumbnail_url), it) }
|
||||
thumbnailUrl?.let { pairs += context.getString(R.string.thumbnail_url) to it }
|
||||
return pairs
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@ package exh.metadata.metadata
|
||||
import android.content.Context
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import exh.metadata.metadata.EightMusesSearchMetadata.Companion.ARTIST_NAMESPACE
|
||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@ -51,11 +50,11 @@ class HBrowseSearchMetadata : RaisedSearchMetadata() {
|
||||
|
||||
override fun getExtraInfoPairs(context: Context): List<Pair<String, String>> {
|
||||
val pairs = mutableListOf<Pair<String, String>>()
|
||||
hbId?.let { pairs += Pair(context.getString(R.string.id), it.toString()) }
|
||||
hbUrl?.let { pairs += Pair(context.getString(R.string.url), it) }
|
||||
thumbnail?.let { pairs += Pair(context.getString(R.string.thumbnail_url), it) }
|
||||
title?.let { pairs += Pair(context.getString(R.string.title), it) }
|
||||
length?.let { pairs += Pair(context.getString(R.string.page_count), it.toString()) }
|
||||
hbId?.let { pairs += context.getString(R.string.id) to it.toString() }
|
||||
hbUrl?.let { pairs += context.getString(R.string.url) to it }
|
||||
thumbnail?.let { pairs += context.getString(R.string.thumbnail_url) to it }
|
||||
title?.let { pairs += context.getString(R.string.title) to it }
|
||||
length?.let { pairs += context.getString(R.string.page_count) to it.toString() }
|
||||
return pairs
|
||||
}
|
||||
|
||||
@ -65,6 +64,7 @@ class HBrowseSearchMetadata : RaisedSearchMetadata() {
|
||||
private const val TITLE_TYPE_MAIN = 0
|
||||
|
||||
const val TAG_TYPE_DEFAULT = 0
|
||||
const val ARTIST_NAMESPACE = "artist"
|
||||
|
||||
fun guessThumbnailUrl(hbid: String): String {
|
||||
return "$BASE_URL/thumbnails/${hbid}_1.jpg#guessed"
|
||||
|
@ -48,11 +48,11 @@ class HentaiCafeSearchMetadata : RaisedSearchMetadata() {
|
||||
|
||||
override fun getExtraInfoPairs(context: Context): List<Pair<String, String>> {
|
||||
val pairs = mutableListOf<Pair<String, String>>()
|
||||
hcId?.let { pairs += Pair(context.getString(R.string.id), it) }
|
||||
readerId?.let { pairs += Pair(context.getString(R.string.reader_id), it) }
|
||||
thumbnailUrl?.let { pairs += Pair(context.getString(R.string.thumbnail_url), it) }
|
||||
title?.let { pairs += Pair(context.getString(R.string.title), it) }
|
||||
artist?.let { pairs += Pair(context.getString(R.string.artist), it) }
|
||||
hcId?.let { pairs += context.getString(R.string.id) to it }
|
||||
readerId?.let { pairs += context.getString(R.string.reader_id) to it }
|
||||
thumbnailUrl?.let { pairs += context.getString(R.string.thumbnail_url) to it }
|
||||
title?.let { pairs += context.getString(R.string.title) to it }
|
||||
artist?.let { pairs += context.getString(R.string.artist) to it }
|
||||
return pairs
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ package exh.metadata.metadata
|
||||
import android.content.Context
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import exh.metadata.EX_DATE_FORMAT
|
||||
import exh.metadata.MetadataUtil
|
||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.Date
|
||||
@ -94,25 +94,27 @@ class HitomiSearchMetadata : RaisedSearchMetadata() {
|
||||
|
||||
override fun getExtraInfoPairs(context: Context): List<Pair<String, String>> {
|
||||
val pairs = mutableListOf<Pair<String, String>>()
|
||||
hlId?.let { pairs += Pair(context.getString(R.string.id), it) }
|
||||
title?.let { pairs += Pair(context.getString(R.string.title), it) }
|
||||
thumbnailUrl?.let { pairs += Pair(context.getString(R.string.thumbnail_url), it) }
|
||||
with(context) {
|
||||
hlId?.let { pairs += getString(R.string.id) to it }
|
||||
title?.let { pairs += getString(R.string.title) to it }
|
||||
thumbnailUrl?.let { pairs += getString(R.string.thumbnail_url) to it }
|
||||
val artists = artists.joinToString()
|
||||
if (artists.isNotBlank()) {
|
||||
pairs += Pair(context.getString(R.string.artist), artists)
|
||||
pairs += getString(R.string.artist) to artists
|
||||
}
|
||||
group?.let { pairs += Pair(context.getString(R.string.group), it) }
|
||||
genre?.let { pairs += Pair(context.getString(R.string.genre), it) }
|
||||
language?.let { pairs += Pair(context.getString(R.string.language), it) }
|
||||
group?.let { pairs += getString(R.string.group) to it }
|
||||
genre?.let { pairs += getString(R.string.genre) to it }
|
||||
language?.let { pairs += getString(R.string.language) to it }
|
||||
val series = series.joinToString()
|
||||
if (series.isNotBlank()) {
|
||||
pairs += Pair(context.getString(R.string.series), series)
|
||||
pairs += getString(R.string.series) to series
|
||||
}
|
||||
val characters = characters.joinToString()
|
||||
if (characters.isNotBlank()) {
|
||||
pairs += Pair(context.getString(R.string.characters), characters)
|
||||
pairs += getString(R.string.characters) to characters
|
||||
}
|
||||
uploadDate?.let { pairs += getString(R.string.date_posted) to MetadataUtil.EX_DATE_FORMAT.format(Date(it)) }
|
||||
}
|
||||
uploadDate?.let { pairs += Pair(context.getString(R.string.date_posted), EX_DATE_FORMAT.format(Date(it))) }
|
||||
return pairs
|
||||
}
|
||||
|
||||
|
@ -78,24 +78,24 @@ class MangaDexSearchMetadata : RaisedSearchMetadata() {
|
||||
|
||||
override fun getExtraInfoPairs(context: Context): List<Pair<String, String>> {
|
||||
val pairs = mutableListOf<Pair<String, String>>()
|
||||
mdId?.let { pairs += Pair(context.getString(R.string.id), it) }
|
||||
mdUrl?.let { pairs += Pair(context.getString(R.string.url), it) }
|
||||
thumbnail_url?.let { pairs += Pair(context.getString(R.string.thumbnail_url), it) }
|
||||
title?.let { pairs += Pair(context.getString(R.string.title), it) }
|
||||
author?.let { pairs += Pair(context.getString(R.string.author), it) }
|
||||
artist?.let { pairs += Pair(context.getString(R.string.artist), it) }
|
||||
lang_flag?.let { pairs += Pair(context.getString(R.string.language), it) }
|
||||
last_chapter_number?.let { pairs += Pair(context.getString(R.string.last_chapter_number), it.toString()) }
|
||||
rating?.let { pairs += Pair(context.getString(R.string.average_rating), it) }
|
||||
users?.let { pairs += Pair(context.getString(R.string.total_ratings), it) }
|
||||
status?.let { pairs += Pair(context.getString(R.string.status), it.toString()) }
|
||||
missing_chapters?.let { pairs += Pair(context.getString(R.string.missing_chapters), it) }
|
||||
follow_status?.let { pairs += Pair(context.getString(R.string.follow_status), it.toString()) }
|
||||
anilist_id?.let { pairs += Pair(context.getString(R.string.anilist_id), it) }
|
||||
kitsu_id?.let { pairs += Pair(context.getString(R.string.kitsu_id), it) }
|
||||
my_anime_list_id?.let { pairs += Pair(context.getString(R.string.mal_id), it) }
|
||||
manga_updates_id?.let { pairs += Pair(context.getString(R.string.manga_updates_id), it) }
|
||||
anime_planet_id?.let { pairs += Pair(context.getString(R.string.anime_planet_id), it) }
|
||||
mdId?.let { pairs += context.getString(R.string.id) to it }
|
||||
mdUrl?.let { pairs += context.getString(R.string.url) to it }
|
||||
thumbnail_url?.let { pairs += context.getString(R.string.thumbnail_url) to it }
|
||||
title?.let { pairs += context.getString(R.string.title) to it }
|
||||
author?.let { pairs += context.getString(R.string.author) to it }
|
||||
artist?.let { pairs += context.getString(R.string.artist) to it }
|
||||
lang_flag?.let { pairs += context.getString(R.string.language) to it }
|
||||
last_chapter_number?.let { pairs += context.getString(R.string.last_chapter_number) to it.toString() }
|
||||
rating?.let { pairs += context.getString(R.string.average_rating) to it }
|
||||
users?.let { pairs += context.getString(R.string.total_ratings) to it }
|
||||
status?.let { pairs += context.getString(R.string.status) to it.toString() }
|
||||
missing_chapters?.let { pairs += context.getString(R.string.missing_chapters) to it }
|
||||
follow_status?.let { pairs += context.getString(R.string.follow_status) to it.toString() }
|
||||
anilist_id?.let { pairs += context.getString(R.string.anilist_id) to it }
|
||||
kitsu_id?.let { pairs += context.getString(R.string.kitsu_id) to it }
|
||||
my_anime_list_id?.let { pairs += context.getString(R.string.mal_id) to it }
|
||||
manga_updates_id?.let { pairs += context.getString(R.string.manga_updates_id) to it }
|
||||
anime_planet_id?.let { pairs += context.getString(R.string.anime_planet_id) to it }
|
||||
return pairs
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,7 @@ package exh.metadata.metadata
|
||||
import android.content.Context
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import exh.metadata.EX_DATE_FORMAT
|
||||
import exh.metadata.ONGOING_SUFFIX
|
||||
import exh.metadata.MetadataUtil
|
||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.Date
|
||||
@ -65,7 +64,7 @@ class NHentaiSearchMetadata : RaisedSearchMetadata() {
|
||||
// We default to completed
|
||||
manga.status = SManga.COMPLETED
|
||||
englishTitle?.let { t ->
|
||||
ONGOING_SUFFIX.find {
|
||||
MetadataUtil.ONGOING_SUFFIX.find {
|
||||
t.endsWith(it, ignoreCase = true)
|
||||
}?.let {
|
||||
manga.status = SManga.ONGOING
|
||||
@ -77,17 +76,17 @@ class NHentaiSearchMetadata : RaisedSearchMetadata() {
|
||||
|
||||
override fun getExtraInfoPairs(context: Context): List<Pair<String, String>> {
|
||||
val pairs = mutableListOf<Pair<String, String>>()
|
||||
nhId?.let { pairs += Pair(context.getString(R.string.id), it.toString()) }
|
||||
uploadDate?.let { pairs += Pair(context.getString(R.string.date_posted), EX_DATE_FORMAT.format(Date(it * 1000))) }
|
||||
favoritesCount?.let { pairs += Pair(context.getString(R.string.total_favorites), it.toString()) }
|
||||
mediaId?.let { pairs += Pair(context.getString(R.string.media_id), it) }
|
||||
japaneseTitle?.let { pairs += Pair(context.getString(R.string.japanese_title), it) }
|
||||
englishTitle?.let { pairs += Pair(context.getString(R.string.english_title), it) }
|
||||
shortTitle?.let { pairs += Pair(context.getString(R.string.short_title), it) }
|
||||
coverImageType?.let { pairs += Pair(context.getString(R.string.cover_image_file_type), it) }
|
||||
pageImageTypes.size.let { pairs += Pair(context.getString(R.string.page_count), it.toString()) }
|
||||
thumbnailImageType?.let { pairs += Pair(context.getString(R.string.thumbnail_image_file_type), it) }
|
||||
scanlator?.let { pairs += Pair(context.getString(R.string.scanlator), it) }
|
||||
nhId?.let { pairs += context.getString(R.string.id) to it.toString() }
|
||||
uploadDate?.let { pairs += context.getString(R.string.date_posted) to MetadataUtil.EX_DATE_FORMAT.format(Date(it * 1000)) }
|
||||
favoritesCount?.let { pairs += context.getString(R.string.total_favorites) to it.toString() }
|
||||
mediaId?.let { pairs += context.getString(R.string.media_id) to it }
|
||||
japaneseTitle?.let { pairs += context.getString(R.string.japanese_title) to it }
|
||||
englishTitle?.let { pairs += context.getString(R.string.english_title) to it }
|
||||
shortTitle?.let { pairs += context.getString(R.string.short_title) to it }
|
||||
coverImageType?.let { pairs += context.getString(R.string.cover_image_file_type) to it }
|
||||
pageImageTypes.size.let { pairs += context.getString(R.string.page_count) to it.toString() }
|
||||
thumbnailImageType?.let { pairs += context.getString(R.string.thumbnail_image_file_type) to it }
|
||||
scanlator?.let { pairs += context.getString(R.string.scanlator) to it }
|
||||
return pairs
|
||||
}
|
||||
|
||||
|
@ -95,19 +95,19 @@ class PervEdenSearchMetadata : RaisedSearchMetadata() {
|
||||
|
||||
override fun getExtraInfoPairs(context: Context): List<Pair<String, String>> {
|
||||
val pairs = mutableListOf<Pair<String, String>>()
|
||||
pvId?.let { pairs += Pair(context.getString(R.string.id), it) }
|
||||
url?.let { pairs += Pair(context.getString(R.string.url), it) }
|
||||
thumbnailUrl?.let { pairs += Pair(context.getString(R.string.thumbnail_url), it) }
|
||||
title?.let { pairs += Pair(context.getString(R.string.title), it) }
|
||||
pvId?.let { pairs += context.getString(R.string.id) to it }
|
||||
url?.let { pairs += context.getString(R.string.url) to it }
|
||||
thumbnailUrl?.let { pairs += context.getString(R.string.thumbnail_url) to it }
|
||||
title?.let { pairs += context.getString(R.string.title) to it }
|
||||
val altTitles = altTitles.joinToString()
|
||||
if (altTitles.isNotBlank()) {
|
||||
pairs += Pair(context.getString(R.string.alt_titles), altTitles)
|
||||
pairs += context.getString(R.string.alt_titles) to altTitles
|
||||
}
|
||||
artist?.let { pairs += Pair(context.getString(R.string.artist), it) }
|
||||
genre?.let { pairs += Pair(context.getString(R.string.genre), it) }
|
||||
rating?.let { pairs += Pair(context.getString(R.string.average_rating), it.toString()) }
|
||||
status?.let { pairs += Pair(context.getString(R.string.status), it) }
|
||||
lang?.let { pairs += Pair(context.getString(R.string.language), it) }
|
||||
artist?.let { pairs += context.getString(R.string.artist) to it }
|
||||
genre?.let { pairs += context.getString(R.string.genre) to it }
|
||||
rating?.let { pairs += context.getString(R.string.average_rating) to it.toString() }
|
||||
status?.let { pairs += context.getString(R.string.status) to it }
|
||||
lang?.let { pairs += context.getString(R.string.language) to it }
|
||||
return pairs
|
||||
}
|
||||
|
||||
|
@ -64,16 +64,16 @@ class PururinSearchMetadata : RaisedSearchMetadata() {
|
||||
|
||||
override fun getExtraInfoPairs(context: Context): List<Pair<String, String>> {
|
||||
val pairs = mutableListOf<Pair<String, String>>()
|
||||
prId?.let { pairs += Pair(context.getString(R.string.id), it.toString()) }
|
||||
title?.let { pairs += Pair(context.getString(R.string.title), it) }
|
||||
altTitle?.let { pairs += Pair(context.getString(R.string.alt_title), it) }
|
||||
thumbnailUrl?.let { pairs += Pair(context.getString(R.string.thumbnail_url), it) }
|
||||
uploaderDisp?.let { pairs += Pair(context.getString(R.string.uploader_capital), it) }
|
||||
uploader?.let { pairs += Pair(context.getString(R.string.uploader), it) }
|
||||
pages?.let { pairs += Pair(context.getString(R.string.page_count), it.toString()) }
|
||||
fileSize?.let { pairs += Pair(context.getString(R.string.gallery_size), it) }
|
||||
ratingCount?.let { pairs += Pair(context.getString(R.string.total_ratings), it.toString()) }
|
||||
averageRating?.let { pairs += Pair(context.getString(R.string.average_rating), it.toString()) }
|
||||
prId?.let { pairs += context.getString(R.string.id) to it.toString() }
|
||||
title?.let { pairs += context.getString(R.string.title) to it }
|
||||
altTitle?.let { pairs += context.getString(R.string.alt_title) to it }
|
||||
thumbnailUrl?.let { pairs += context.getString(R.string.thumbnail_url) to it }
|
||||
uploaderDisp?.let { pairs += context.getString(R.string.uploader_capital) to it }
|
||||
uploader?.let { pairs += context.getString(R.string.uploader) to it }
|
||||
pages?.let { pairs += context.getString(R.string.page_count) to it.toString() }
|
||||
fileSize?.let { pairs += context.getString(R.string.gallery_size) to it }
|
||||
ratingCount?.let { pairs += context.getString(R.string.total_ratings) to it.toString() }
|
||||
averageRating?.let { pairs += context.getString(R.string.average_rating) to it.toString() }
|
||||
return pairs
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ import android.content.Context
|
||||
import android.net.Uri
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import exh.metadata.EX_DATE_FORMAT
|
||||
import exh.metadata.MetadataUtil
|
||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.text.SimpleDateFormat
|
||||
@ -82,25 +82,25 @@ class TsuminoSearchMetadata : RaisedSearchMetadata() {
|
||||
|
||||
override fun getExtraInfoPairs(context: Context): List<Pair<String, String>> {
|
||||
val pairs = mutableListOf<Pair<String, String>>()
|
||||
tmId?.let { pairs += Pair(context.getString(R.string.id), it.toString()) }
|
||||
title?.let { pairs += Pair(context.getString(R.string.title), it) }
|
||||
uploader?.let { pairs += Pair(context.getString(R.string.uploader), it) }
|
||||
uploadDate?.let { pairs += Pair(context.getString(R.string.date_posted), EX_DATE_FORMAT.format(Date(it))) }
|
||||
length?.let { pairs += Pair(context.getString(R.string.page_count), it.toString()) }
|
||||
ratingString?.let { pairs += Pair(context.getString(R.string.rating_string), it) }
|
||||
averageRating?.let { pairs += Pair(context.getString(R.string.average_rating), it.toString()) }
|
||||
userRatings?.let { pairs += Pair(context.getString(R.string.total_ratings), it.toString()) }
|
||||
favorites?.let { pairs += Pair(context.getString(R.string.total_favorites), it.toString()) }
|
||||
category?.let { pairs += Pair(context.getString(R.string.genre), it) }
|
||||
collection?.let { pairs += Pair(context.getString(R.string.collection), it) }
|
||||
group?.let { pairs += Pair(context.getString(R.string.group), it) }
|
||||
tmId?.let { pairs += context.getString(R.string.id) to it.toString() }
|
||||
title?.let { pairs += context.getString(R.string.title) to it }
|
||||
uploader?.let { pairs += context.getString(R.string.uploader) to it }
|
||||
uploadDate?.let { pairs += context.getString(R.string.date_posted) to MetadataUtil.EX_DATE_FORMAT.format(Date(it)) }
|
||||
length?.let { pairs += context.getString(R.string.page_count) to it.toString() }
|
||||
ratingString?.let { pairs += context.getString(R.string.rating_string) to it }
|
||||
averageRating?.let { pairs += context.getString(R.string.average_rating) to it.toString() }
|
||||
userRatings?.let { pairs += context.getString(R.string.total_ratings) to it.toString() }
|
||||
favorites?.let { pairs += context.getString(R.string.total_favorites) to it.toString() }
|
||||
category?.let { pairs += context.getString(R.string.genre) to it }
|
||||
collection?.let { pairs += context.getString(R.string.collection) to it }
|
||||
group?.let { pairs += context.getString(R.string.group) to it }
|
||||
val parodiesString = parody.joinToString()
|
||||
if (parodiesString.isNotEmpty()) {
|
||||
pairs += Pair(context.getString(R.string.parodies), parodiesString)
|
||||
pairs += context.getString(R.string.parodies) to parodiesString
|
||||
}
|
||||
val charactersString = character.joinToString()
|
||||
if (charactersString.isNotEmpty()) {
|
||||
pairs += Pair(context.getString(R.string.characters), charactersString)
|
||||
pairs += context.getString(R.string.characters) to charactersString
|
||||
}
|
||||
return pairs
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package exh.search
|
||||
|
||||
import exh.plusAssign
|
||||
import exh.search.SearchEngine.Companion.escapeLike
|
||||
|
||||
class Text : QueryComponent() {
|
||||
val components = mutableListOf<TextComponent>()
|
||||
@ -44,7 +43,7 @@ class Text : QueryComponent() {
|
||||
val builder = StringBuilder()
|
||||
for (component in components) {
|
||||
when (component) {
|
||||
is StringTextComponent -> builder += escapeLike(component.value)
|
||||
is StringTextComponent -> builder += SearchEngine.escapeLike(component.value)
|
||||
is SingleWildcard -> builder += "_"
|
||||
is MultiWildcard -> builder += "%"
|
||||
}
|
||||
@ -60,5 +59,5 @@ class Text : QueryComponent() {
|
||||
rawText!!
|
||||
}
|
||||
|
||||
fun rawTextEscapedForLike() = escapeLike(rawTextOnly())
|
||||
fun rawTextEscapedForLike() = SearchEngine.escapeLike(rawTextOnly())
|
||||
}
|
||||
|
@ -235,21 +235,22 @@ class EnhancedHttpSource(
|
||||
originalSource
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun Source.getMainSource(): Source {
|
||||
return if (this is EnhancedHttpSource) {
|
||||
fun Source.getMainSource(): Source = if (this is EnhancedHttpSource) {
|
||||
this.source()
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
fun Source.getOriginalSource(): Source {
|
||||
return if (this is EnhancedHttpSource) {
|
||||
|
||||
fun Source.getOriginalSource(): Source = if (this is EnhancedHttpSource) {
|
||||
this.originalSource
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Source.getEnhancedSource(): Source = if (this is EnhancedHttpSource) {
|
||||
this.enhancedSource
|
||||
} else {
|
||||
this
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import android.webkit.WebResourceRequest
|
||||
import android.webkit.WebResourceResponse
|
||||
import android.webkit.WebView
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import exh.ui.captcha.BrowserActionActivity.Companion.CROSS_WINDOW_SCRIPT_INNER
|
||||
import org.jsoup.nodes.DataNode
|
||||
import org.jsoup.nodes.Element
|
||||
import java.nio.charset.Charset
|
||||
@ -24,7 +23,7 @@ class AutoSolvingWebViewClient(
|
||||
val oReq = request.toOkHttpRequest()
|
||||
val response = activity.httpClient.newCall(oReq).execute()
|
||||
val doc = response.asJsoup()
|
||||
doc.body().appendChild(Element("script").appendChild(DataNode(CROSS_WINDOW_SCRIPT_INNER)))
|
||||
doc.body().appendChild(Element("script").appendChild(DataNode(BrowserActionActivity.CROSS_WINDOW_SCRIPT_INNER)))
|
||||
return WebResourceResponse(
|
||||
"text/html",
|
||||
"UTF-8",
|
||||
|
@ -16,7 +16,7 @@ import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import exh.metadata.metadata.base.FlatMetadata
|
||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
||||
import exh.source.getMainSource
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
|
@ -1,23 +1,19 @@
|
||||
package exh.ui.metadata.adapters
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.graphics.Color
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.databinding.DescriptionAdapterEhBinding
|
||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import exh.metadata.humanReadableByteCount
|
||||
import exh.metadata.MetadataUtil
|
||||
import exh.metadata.bindDrawable
|
||||
import exh.metadata.metadata.EHentaiSearchMetadata
|
||||
import exh.ui.metadata.MetadataViewController
|
||||
import exh.util.SourceTagsUtil
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
@ -25,7 +21,6 @@ import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.android.view.clicks
|
||||
import reactivecircus.flowbinding.android.view.longClicks
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class EHentaiDescriptionAdapter(
|
||||
private val controller: MangaController
|
||||
@ -51,52 +46,23 @@ class EHentaiDescriptionAdapter(
|
||||
val meta = controller.presenter.meta
|
||||
if (meta == null || meta !is EHentaiSearchMetadata) return
|
||||
|
||||
val genre = meta.genre
|
||||
if (genre != null) {
|
||||
val pair = when (genre) {
|
||||
"doujinshi" -> Pair(SourceTagsUtil.DOUJINSHI_COLOR, R.string.doujinshi)
|
||||
"manga" -> Pair(SourceTagsUtil.MANGA_COLOR, R.string.manga)
|
||||
"artistcg" -> Pair(SourceTagsUtil.ARTIST_CG_COLOR, R.string.artist_cg)
|
||||
"gamecg" -> Pair(SourceTagsUtil.GAME_CG_COLOR, R.string.game_cg)
|
||||
"western" -> Pair(SourceTagsUtil.WESTERN_COLOR, R.string.western)
|
||||
"non-h" -> Pair(SourceTagsUtil.NON_H_COLOR, R.string.non_h)
|
||||
"imageset" -> Pair(SourceTagsUtil.IMAGE_SET_COLOR, R.string.image_set)
|
||||
"cosplay" -> Pair(SourceTagsUtil.COSPLAY_COLOR, R.string.cosplay)
|
||||
"asianporn" -> Pair(SourceTagsUtil.ASIAN_PORN_COLOR, R.string.asian_porn)
|
||||
"misc" -> Pair(SourceTagsUtil.MISC_COLOR, R.string.misc)
|
||||
else -> Pair("", 0)
|
||||
}
|
||||
|
||||
if (pair.first.isNotBlank()) {
|
||||
binding.genre.setBackgroundColor(Color.parseColor(pair.first))
|
||||
binding.genre.text = itemView.context.getString(pair.second)
|
||||
} else binding.genre.text = genre
|
||||
} else binding.genre.setText(R.string.unknown)
|
||||
binding.genre.text = meta.genre?.let { MetadataUtil.getGenreAndColour(itemView.context, it) }?.let {
|
||||
binding.genre.setBackgroundColor(it.first)
|
||||
it.second
|
||||
} ?: meta.genre ?: itemView.context.getString(R.string.unknown)
|
||||
|
||||
binding.visible.text = itemView.context.getString(R.string.is_visible, meta.visible ?: itemView.context.getString(R.string.unknown))
|
||||
|
||||
binding.favorites.text = (meta.favorites ?: 0).toString()
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_book_24dp)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.favorites.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.favorites.bindDrawable(itemView.context, R.drawable.ic_book_24dp)
|
||||
|
||||
binding.uploader.text = meta.uploader ?: itemView.context.getString(R.string.unknown)
|
||||
|
||||
binding.size.text = humanReadableByteCount(meta.size ?: 0, true)
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_outline_sd_card_24)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.size.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.size.text = MetadataUtil.humanReadableByteCount(meta.size ?: 0, true)
|
||||
binding.size.bindDrawable(itemView.context, R.drawable.ic_outline_sd_card_24)
|
||||
|
||||
binding.pages.text = itemView.resources.getQuantityString(R.plurals.num_pages, meta.length ?: 0, meta.length ?: 0)
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_baseline_menu_book_24)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.pages.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.pages.bindDrawable(itemView.context, R.drawable.ic_baseline_menu_book_24)
|
||||
|
||||
val language = meta.language ?: itemView.context.getString(R.string.unknown)
|
||||
binding.language.text = if (meta.translated == true) {
|
||||
@ -106,29 +72,11 @@ class EHentaiDescriptionAdapter(
|
||||
}
|
||||
|
||||
val ratingFloat = meta.averageRating?.toFloat()
|
||||
val name = when (((ratingFloat ?: 100F) * 2).roundToInt()) {
|
||||
0 -> R.string.rating0
|
||||
1 -> R.string.rating1
|
||||
2 -> R.string.rating2
|
||||
3 -> R.string.rating3
|
||||
4 -> R.string.rating4
|
||||
5 -> R.string.rating5
|
||||
6 -> R.string.rating6
|
||||
7 -> R.string.rating7
|
||||
8 -> R.string.rating8
|
||||
9 -> R.string.rating9
|
||||
10 -> R.string.rating10
|
||||
else -> R.string.no_rating
|
||||
}
|
||||
binding.ratingBar.rating = ratingFloat ?: 0F
|
||||
@SuppressLint("SetTextI18n")
|
||||
binding.rating.text = (ratingFloat ?: 0F).toString() + " - " + itemView.context.getString(name)
|
||||
binding.rating.text = (ratingFloat ?: 0F).toString() + " - " + MetadataUtil.getRatingString(itemView.context, ratingFloat?.times(2))
|
||||
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_info_24dp)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.moreInfo.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
|
||||
|
||||
listOf(
|
||||
binding.favorites,
|
||||
|
@ -3,15 +3,13 @@ package exh.ui.metadata.adapters
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.databinding.DescriptionAdapter8mBinding
|
||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import exh.metadata.bindDrawable
|
||||
import exh.metadata.metadata.EightMusesSearchMetadata
|
||||
import exh.ui.metadata.MetadataViewController
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@ -48,11 +46,7 @@ class EightMusesDescriptionAdapter(
|
||||
|
||||
binding.title.text = meta.title ?: itemView.context.getString(R.string.unknown)
|
||||
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_info_24dp)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.moreInfo.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
|
||||
|
||||
binding.title.longClicks()
|
||||
.onEach {
|
||||
|
@ -3,15 +3,13 @@ package exh.ui.metadata.adapters
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.databinding.DescriptionAdapterHbBinding
|
||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import exh.metadata.bindDrawable
|
||||
import exh.metadata.metadata.HBrowseSearchMetadata
|
||||
import exh.ui.metadata.MetadataViewController
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@ -47,17 +45,9 @@ class HBrowseDescriptionAdapter(
|
||||
if (meta == null || meta !is HBrowseSearchMetadata) return
|
||||
|
||||
binding.pages.text = itemView.resources.getQuantityString(R.plurals.num_pages, meta.length ?: 0, meta.length ?: 0)
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_baseline_menu_book_24)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.pages.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.pages.bindDrawable(itemView.context, R.drawable.ic_baseline_menu_book_24)
|
||||
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_info_24dp)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.moreInfo.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
|
||||
|
||||
binding.pages.longClicks()
|
||||
.onEach {
|
||||
|
@ -3,15 +3,13 @@ package exh.ui.metadata.adapters
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.databinding.DescriptionAdapterHcBinding
|
||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import exh.metadata.bindDrawable
|
||||
import exh.metadata.metadata.HentaiCafeSearchMetadata
|
||||
import exh.ui.metadata.MetadataViewController
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@ -48,11 +46,7 @@ class HentaiCafeDescriptionAdapter(
|
||||
|
||||
binding.artist.text = meta.artist ?: itemView.context.getString(R.string.unknown)
|
||||
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_info_24dp)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.moreInfo.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
|
||||
|
||||
binding.artist.longClicks()
|
||||
.onEach {
|
||||
|
@ -1,22 +1,18 @@
|
||||
package exh.ui.metadata.adapters
|
||||
|
||||
import android.graphics.Color
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.databinding.DescriptionAdapterHiBinding
|
||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import exh.metadata.EX_DATE_FORMAT
|
||||
import exh.metadata.MetadataUtil
|
||||
import exh.metadata.bindDrawable
|
||||
import exh.metadata.metadata.HitomiSearchMetadata
|
||||
import exh.ui.metadata.MetadataViewController
|
||||
import exh.util.SourceTagsUtil
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
@ -50,37 +46,16 @@ class HitomiDescriptionAdapter(
|
||||
val meta = controller.presenter.meta
|
||||
if (meta == null || meta !is HitomiSearchMetadata) return
|
||||
|
||||
val genre = meta.genre
|
||||
if (genre != null) {
|
||||
val pair = when (genre) {
|
||||
"doujinshi" -> Pair(SourceTagsUtil.DOUJINSHI_COLOR, R.string.doujinshi)
|
||||
"manga" -> Pair(SourceTagsUtil.MANGA_COLOR, R.string.manga)
|
||||
"artist CG" -> Pair(SourceTagsUtil.ARTIST_CG_COLOR, R.string.artist_cg)
|
||||
"game CG" -> Pair(SourceTagsUtil.GAME_CG_COLOR, R.string.game_cg)
|
||||
"western" -> Pair(SourceTagsUtil.WESTERN_COLOR, R.string.western)
|
||||
"non-H" -> Pair(SourceTagsUtil.NON_H_COLOR, R.string.non_h)
|
||||
"image Set" -> Pair(SourceTagsUtil.IMAGE_SET_COLOR, R.string.image_set)
|
||||
"cosplay" -> Pair(SourceTagsUtil.COSPLAY_COLOR, R.string.cosplay)
|
||||
"asian Porn" -> Pair(SourceTagsUtil.ASIAN_PORN_COLOR, R.string.asian_porn)
|
||||
"misc" -> Pair(SourceTagsUtil.MISC_COLOR, R.string.misc)
|
||||
else -> Pair("", 0)
|
||||
}
|
||||
binding.genre.text = meta.genre?.let { MetadataUtil.getGenreAndColour(itemView.context, it) }?.let {
|
||||
binding.genre.setBackgroundColor(it.first)
|
||||
it.second
|
||||
} ?: meta.genre ?: itemView.context.getString(R.string.unknown)
|
||||
|
||||
if (pair.first.isNotBlank()) {
|
||||
binding.genre.setBackgroundColor(Color.parseColor(pair.first))
|
||||
binding.genre.text = itemView.context.getString(pair.second)
|
||||
} else binding.genre.text = genre
|
||||
} else binding.genre.setText(R.string.unknown)
|
||||
|
||||
binding.whenPosted.text = EX_DATE_FORMAT.format(Date(meta.uploadDate ?: 0))
|
||||
binding.whenPosted.text = MetadataUtil.EX_DATE_FORMAT.format(Date(meta.uploadDate ?: 0))
|
||||
binding.group.text = meta.group ?: itemView.context.getString(R.string.unknown)
|
||||
binding.language.text = meta.language ?: itemView.context.getString(R.string.unknown)
|
||||
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_info_24dp)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.moreInfo.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
|
||||
|
||||
listOf(
|
||||
binding.genre,
|
||||
|
@ -4,15 +4,14 @@ import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.databinding.DescriptionAdapterMdBinding
|
||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import exh.metadata.MetadataUtil.getRatingString
|
||||
import exh.metadata.bindDrawable
|
||||
import exh.metadata.metadata.MangaDexSearchMetadata
|
||||
import exh.ui.metadata.MetadataViewController
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@ -23,7 +22,6 @@ import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.android.view.clicks
|
||||
import reactivecircus.flowbinding.android.view.longClicks
|
||||
import kotlin.math.round
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class MangaDexDescriptionAdapter(
|
||||
private val controller: MangaController
|
||||
@ -50,31 +48,12 @@ class MangaDexDescriptionAdapter(
|
||||
val meta = controller.presenter.meta
|
||||
if (meta == null || meta !is MangaDexSearchMetadata) return
|
||||
|
||||
val ratingFloat = meta.rating?.toFloatOrNull()?.div(2F)
|
||||
val name = when (((ratingFloat ?: 100F) * 2).roundToInt()) {
|
||||
0 -> R.string.rating0
|
||||
1 -> R.string.rating1
|
||||
2 -> R.string.rating2
|
||||
3 -> R.string.rating3
|
||||
4 -> R.string.rating4
|
||||
5 -> R.string.rating5
|
||||
6 -> R.string.rating6
|
||||
7 -> R.string.rating7
|
||||
8 -> R.string.rating8
|
||||
9 -> R.string.rating9
|
||||
10 -> R.string.rating10
|
||||
else -> R.string.no_rating
|
||||
}
|
||||
|
||||
binding.ratingBar.rating = ratingFloat ?: 0F
|
||||
val ratingFloat = meta.rating?.toFloatOrNull()
|
||||
binding.ratingBar.rating = ratingFloat?.div(2F) ?: 0F
|
||||
@SuppressLint("SetTextI18n")
|
||||
binding.rating.text = (round((meta.rating?.toFloatOrNull() ?: 0F) * 100.0) / 100.0).toString() + " - " + itemView.context.getString(name)
|
||||
binding.rating.text = (round((meta.rating?.toFloatOrNull() ?: 0F) * 100.0) / 100.0).toString() + " - " + getRatingString(itemView.context, ratingFloat)
|
||||
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_info_24dp)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.moreInfo.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
|
||||
|
||||
binding.rating.longClicks()
|
||||
.onEach {
|
||||
|
@ -1,23 +1,19 @@
|
||||
package exh.ui.metadata.adapters
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.graphics.Color
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.databinding.DescriptionAdapterNhBinding
|
||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import exh.metadata.EX_DATE_FORMAT
|
||||
import exh.metadata.MetadataUtil
|
||||
import exh.metadata.bindDrawable
|
||||
import exh.metadata.metadata.NHentaiSearchMetadata
|
||||
import exh.ui.metadata.MetadataViewController
|
||||
import exh.util.SourceTagsUtil
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
@ -52,60 +48,30 @@ class NHentaiDescriptionAdapter(
|
||||
val meta = controller.presenter.meta
|
||||
if (meta == null || meta !is NHentaiSearchMetadata) return
|
||||
|
||||
var category: String? = null
|
||||
meta.tags.filter { it.namespace == NHentaiSearchMetadata.NHENTAI_CATEGORIES_NAMESPACE }.let { tags ->
|
||||
if (tags.isNotEmpty()) category = tags.joinToString(transform = { it.name })
|
||||
binding.genre.text = meta.tags.filter { it.namespace == NHentaiSearchMetadata.NHENTAI_CATEGORIES_NAMESPACE }.let { tags ->
|
||||
if (tags.isNotEmpty()) tags.joinToString(transform = { it.name }) else null
|
||||
}.let { categoriesString ->
|
||||
categoriesString?.let { MetadataUtil.getGenreAndColour(itemView.context, it) }?.let {
|
||||
binding.genre.setBackgroundColor(it.first)
|
||||
it.second
|
||||
} ?: categoriesString ?: itemView.context.getString(R.string.unknown)
|
||||
}
|
||||
|
||||
if (category != null) {
|
||||
val pair = when (category) {
|
||||
"doujinshi" -> Pair(SourceTagsUtil.DOUJINSHI_COLOR, R.string.doujinshi)
|
||||
"manga" -> Pair(SourceTagsUtil.MANGA_COLOR, R.string.manga)
|
||||
"artistcg" -> Pair(SourceTagsUtil.ARTIST_CG_COLOR, R.string.artist_cg)
|
||||
"gamecg" -> Pair(SourceTagsUtil.GAME_CG_COLOR, R.string.game_cg)
|
||||
"western" -> Pair(SourceTagsUtil.WESTERN_COLOR, R.string.western)
|
||||
"non-h" -> Pair(SourceTagsUtil.NON_H_COLOR, R.string.non_h)
|
||||
"imageset" -> Pair(SourceTagsUtil.IMAGE_SET_COLOR, R.string.image_set)
|
||||
"cosplay" -> Pair(SourceTagsUtil.COSPLAY_COLOR, R.string.cosplay)
|
||||
"asianporn" -> Pair(SourceTagsUtil.ASIAN_PORN_COLOR, R.string.asian_porn)
|
||||
"misc" -> Pair(SourceTagsUtil.MISC_COLOR, R.string.misc)
|
||||
else -> Pair("", 0)
|
||||
}
|
||||
|
||||
if (pair.first.isNotBlank()) {
|
||||
binding.genre.setBackgroundColor(Color.parseColor(pair.first))
|
||||
binding.genre.text = itemView.context.getString(pair.second)
|
||||
} else binding.genre.text = category
|
||||
} else binding.genre.setText(R.string.unknown)
|
||||
|
||||
meta.favoritesCount?.let {
|
||||
if (it == 0L) return@let
|
||||
binding.favorites.text = it.toString()
|
||||
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_book_24dp)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.favorites.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.favorites.bindDrawable(itemView.context, R.drawable.ic_book_24dp)
|
||||
}
|
||||
|
||||
binding.whenPosted.text = EX_DATE_FORMAT.format(Date((meta.uploadDate ?: 0) * 1000))
|
||||
binding.whenPosted.text = MetadataUtil.EX_DATE_FORMAT.format(Date((meta.uploadDate ?: 0) * 1000))
|
||||
|
||||
binding.pages.text = itemView.resources.getQuantityString(R.plurals.num_pages, meta.pageImageTypes.size, meta.pageImageTypes.size)
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_baseline_menu_book_24)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.pages.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.pages.bindDrawable(itemView.context, R.drawable.ic_baseline_menu_book_24)
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
binding.id.text = "#" + (meta.nhId ?: 0)
|
||||
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_info_24dp)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.moreInfo.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
|
||||
|
||||
listOf(
|
||||
binding.favorites,
|
||||
|
@ -1,22 +1,19 @@
|
||||
package exh.ui.metadata.adapters
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.graphics.Color
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.databinding.DescriptionAdapterPeBinding
|
||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import exh.metadata.MetadataUtil
|
||||
import exh.metadata.bindDrawable
|
||||
import exh.metadata.metadata.PervEdenSearchMetadata
|
||||
import exh.ui.metadata.MetadataViewController
|
||||
import exh.util.SourceTagsUtil
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
@ -26,7 +23,6 @@ import reactivecircus.flowbinding.android.view.clicks
|
||||
import reactivecircus.flowbinding.android.view.longClicks
|
||||
import java.util.Locale
|
||||
import kotlin.math.round
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class PervEdenDescriptionAdapter(
|
||||
private val controller: MangaController
|
||||
@ -52,22 +48,10 @@ class PervEdenDescriptionAdapter(
|
||||
val meta = controller.presenter.meta
|
||||
if (meta == null || meta !is PervEdenSearchMetadata) return
|
||||
|
||||
val genre = meta.genre
|
||||
if (genre != null) {
|
||||
val pair = when (genre) {
|
||||
"Doujinshi" -> Pair(SourceTagsUtil.DOUJINSHI_COLOR, R.string.doujinshi)
|
||||
"Japanese Manga" -> Pair(SourceTagsUtil.MANGA_COLOR, R.string.manga)
|
||||
"Korean Manhwa" -> Pair(SourceTagsUtil.ARTIST_CG_COLOR, R.string.manhwa)
|
||||
"Chinese Manhua" -> Pair(SourceTagsUtil.GAME_CG_COLOR, R.string.manhua)
|
||||
"Comic" -> Pair(SourceTagsUtil.WESTERN_COLOR, R.string.comic)
|
||||
else -> Pair("", 0)
|
||||
}
|
||||
|
||||
if (pair.first.isNotBlank()) {
|
||||
binding.genre.setBackgroundColor(Color.parseColor(pair.first))
|
||||
binding.genre.text = itemView.context.getString(pair.second)
|
||||
} else binding.genre.text = genre
|
||||
} else binding.genre.setText(R.string.unknown)
|
||||
binding.genre.text = meta.genre?.let { MetadataUtil.getGenreAndColour(itemView.context, it) }?.let {
|
||||
binding.genre.setBackgroundColor(it.first)
|
||||
it.second
|
||||
} ?: meta.genre ?: itemView.context.getString(R.string.unknown)
|
||||
|
||||
val language = meta.lang
|
||||
binding.language.text = if (language != null) {
|
||||
@ -75,29 +59,11 @@ class PervEdenDescriptionAdapter(
|
||||
local.displayName
|
||||
} else itemView.context.getString(R.string.unknown)
|
||||
|
||||
val name = when (((meta.rating ?: 100F) * 2).roundToInt()) {
|
||||
0 -> R.string.rating0
|
||||
1 -> R.string.rating1
|
||||
2 -> R.string.rating2
|
||||
3 -> R.string.rating3
|
||||
4 -> R.string.rating4
|
||||
5 -> R.string.rating5
|
||||
6 -> R.string.rating6
|
||||
7 -> R.string.rating7
|
||||
8 -> R.string.rating8
|
||||
9 -> R.string.rating9
|
||||
10 -> R.string.rating10
|
||||
else -> R.string.no_rating
|
||||
}
|
||||
binding.ratingBar.rating = meta.rating ?: 0F
|
||||
@SuppressLint("SetTextI18n")
|
||||
binding.rating.text = (round((meta.rating ?: 0F) * 100.0) / 100.0).toString() + " - " + itemView.context.getString(name)
|
||||
binding.rating.text = (round((meta.rating ?: 0F) * 100.0) / 100.0).toString() + " - " + MetadataUtil.getRatingString(itemView.context, meta.rating?.times(2))
|
||||
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_info_24dp)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.moreInfo.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
|
||||
|
||||
listOf(
|
||||
binding.genre,
|
||||
|
@ -1,23 +1,19 @@
|
||||
package exh.ui.metadata.adapters
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.graphics.Color
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.databinding.DescriptionAdapterPuBinding
|
||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import exh.metadata.MetadataUtil
|
||||
import exh.metadata.bindDrawable
|
||||
import exh.metadata.metadata.PururinSearchMetadata
|
||||
import exh.metadata.metadata.PururinSearchMetadata.Companion.TAG_NAMESPACE_CATEGORY
|
||||
import exh.ui.metadata.MetadataViewController
|
||||
import exh.util.SourceTagsUtil
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
@ -26,7 +22,6 @@ import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.android.view.clicks
|
||||
import reactivecircus.flowbinding.android.view.longClicks
|
||||
import kotlin.math.round
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class PururinDescriptionAdapter(
|
||||
private val controller: MangaController
|
||||
@ -52,64 +47,28 @@ class PururinDescriptionAdapter(
|
||||
val meta = controller.presenter.meta
|
||||
if (meta == null || meta !is PururinSearchMetadata) return
|
||||
|
||||
val genre = meta.tags.find { it.namespace == TAG_NAMESPACE_CATEGORY }
|
||||
if (genre != null) {
|
||||
val pair = when (genre.name) {
|
||||
"doujinshi" -> Pair(SourceTagsUtil.DOUJINSHI_COLOR, R.string.doujinshi)
|
||||
"manga" -> Pair(SourceTagsUtil.MANGA_COLOR, R.string.manga)
|
||||
"artist-cg" -> Pair(SourceTagsUtil.ARTIST_CG_COLOR, R.string.artist_cg)
|
||||
"game-cg" -> Pair(SourceTagsUtil.GAME_CG_COLOR, R.string.game_cg)
|
||||
"artbook" -> Pair(SourceTagsUtil.IMAGE_SET_COLOR, R.string.artbook)
|
||||
"webtoon" -> Pair(SourceTagsUtil.NON_H_COLOR, R.string.webtoon)
|
||||
else -> Pair("", 0)
|
||||
binding.genre.text = meta.tags.find { it.namespace == PururinSearchMetadata.TAG_NAMESPACE_CATEGORY }.let { genre ->
|
||||
genre?.let { MetadataUtil.getGenreAndColour(itemView.context, it.name) }?.let {
|
||||
binding.genre.setBackgroundColor(it.first)
|
||||
it.second
|
||||
} ?: genre?.name ?: itemView.context.getString(R.string.unknown)
|
||||
}
|
||||
|
||||
if (pair.first.isNotBlank()) {
|
||||
binding.genre.setBackgroundColor(Color.parseColor(pair.first))
|
||||
binding.genre.text = itemView.context.getString(pair.second)
|
||||
} else binding.genre.text = genre.name
|
||||
} else binding.genre.setText(R.string.unknown)
|
||||
|
||||
binding.uploader.text = meta.uploaderDisp ?: meta.uploader ?: ""
|
||||
|
||||
binding.size.text = meta.fileSize ?: itemView.context.getString(R.string.unknown)
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_outline_sd_card_24)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.size.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.size.bindDrawable(itemView.context, R.drawable.ic_outline_sd_card_24)
|
||||
|
||||
binding.pages.text = itemView.resources.getQuantityString(R.plurals.num_pages, meta.pages ?: 0, meta.pages ?: 0)
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_baseline_menu_book_24)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.pages.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.pages.bindDrawable(itemView.context, R.drawable.ic_baseline_menu_book_24)
|
||||
|
||||
val ratingFloat = meta.averageRating?.toFloat()
|
||||
val name = when (((ratingFloat ?: 100F) * 2).roundToInt()) {
|
||||
0 -> R.string.rating0
|
||||
1 -> R.string.rating1
|
||||
2 -> R.string.rating2
|
||||
3 -> R.string.rating3
|
||||
4 -> R.string.rating4
|
||||
5 -> R.string.rating5
|
||||
6 -> R.string.rating6
|
||||
7 -> R.string.rating7
|
||||
8 -> R.string.rating8
|
||||
9 -> R.string.rating9
|
||||
10 -> R.string.rating10
|
||||
else -> R.string.no_rating
|
||||
}
|
||||
binding.ratingBar.rating = ratingFloat ?: 0F
|
||||
@SuppressLint("SetTextI18n")
|
||||
binding.rating.text = (round((ratingFloat ?: 0F) * 100.0) / 100.0).toString() + " - " + itemView.context.getString(name)
|
||||
binding.rating.text = (round((ratingFloat ?: 0F) * 100.0) / 100.0).toString() + " - " + MetadataUtil.getRatingString(itemView.context, ratingFloat?.times(2))
|
||||
|
||||
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
|
||||
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_info_24dp)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.moreInfo.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
listOf(
|
||||
binding.genre,
|
||||
binding.pages,
|
||||
|
@ -1,22 +1,19 @@
|
||||
package exh.ui.metadata.adapters
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.graphics.Color
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.databinding.DescriptionAdapterTsBinding
|
||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import exh.metadata.MetadataUtil
|
||||
import exh.metadata.bindDrawable
|
||||
import exh.metadata.metadata.TsuminoSearchMetadata
|
||||
import exh.ui.metadata.MetadataViewController
|
||||
import exh.util.SourceTagsUtil
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
@ -26,7 +23,6 @@ import reactivecircus.flowbinding.android.view.clicks
|
||||
import reactivecircus.flowbinding.android.view.longClicks
|
||||
import java.util.Date
|
||||
import kotlin.math.round
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class TsuminoDescriptionAdapter(
|
||||
private val controller: MangaController
|
||||
@ -52,64 +48,26 @@ class TsuminoDescriptionAdapter(
|
||||
val meta = controller.presenter.meta
|
||||
if (meta == null || meta !is TsuminoSearchMetadata) return
|
||||
|
||||
val genre = meta.category
|
||||
if (genre != null) {
|
||||
val pair = when (genre) {
|
||||
"Doujinshi" -> Pair(SourceTagsUtil.DOUJINSHI_COLOR, R.string.doujinshi)
|
||||
"Manga" -> Pair(SourceTagsUtil.MANGA_COLOR, R.string.manga)
|
||||
"Artist CG" -> Pair(SourceTagsUtil.ARTIST_CG_COLOR, R.string.artist_cg)
|
||||
"Game CG" -> Pair(SourceTagsUtil.GAME_CG_COLOR, R.string.game_cg)
|
||||
"Video" -> Pair(SourceTagsUtil.WESTERN_COLOR, R.string.video)
|
||||
else -> Pair("", 0)
|
||||
}
|
||||
|
||||
if (pair.first.isNotBlank()) {
|
||||
binding.genre.setBackgroundColor(Color.parseColor(pair.first))
|
||||
binding.genre.text = itemView.context.getString(pair.second)
|
||||
} else binding.genre.text = genre
|
||||
} else binding.genre.setText(R.string.unknown)
|
||||
binding.genre.text = meta.category?.let { MetadataUtil.getGenreAndColour(itemView.context, it) }?.let {
|
||||
binding.genre.setBackgroundColor(it.first)
|
||||
it.second
|
||||
} ?: meta.category ?: itemView.context.getString(R.string.unknown)
|
||||
|
||||
binding.favorites.text = (meta.favorites ?: 0).toString()
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_book_24dp)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.favorites.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.favorites.bindDrawable(itemView.context, R.drawable.ic_book_24dp)
|
||||
|
||||
binding.whenPosted.text = TsuminoSearchMetadata.TSUMINO_DATE_FORMAT.format(Date(meta.uploadDate ?: 0))
|
||||
|
||||
binding.uploader.text = meta.uploader ?: itemView.context.getString(R.string.unknown)
|
||||
|
||||
binding.pages.text = itemView.resources.getQuantityString(R.plurals.num_pages, meta.length ?: 0, meta.length ?: 0)
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_baseline_menu_book_24)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.pages.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.pages.bindDrawable(itemView.context, R.drawable.ic_baseline_menu_book_24)
|
||||
|
||||
val name = when (((meta.averageRating ?: 100F) * 2).roundToInt()) {
|
||||
0 -> R.string.rating0
|
||||
1 -> R.string.rating1
|
||||
2 -> R.string.rating2
|
||||
3 -> R.string.rating3
|
||||
4 -> R.string.rating4
|
||||
5 -> R.string.rating5
|
||||
6 -> R.string.rating6
|
||||
7 -> R.string.rating7
|
||||
8 -> R.string.rating8
|
||||
9 -> R.string.rating9
|
||||
10 -> R.string.rating10
|
||||
else -> R.string.no_rating
|
||||
}
|
||||
binding.ratingBar.rating = meta.averageRating ?: 0F
|
||||
@SuppressLint("SetTextI18n")
|
||||
binding.rating.text = (round((meta.averageRating ?: 0F) * 100.0) / 100.0).toString() + " - " + itemView.context.getString(name)
|
||||
binding.rating.text = (round((meta.averageRating ?: 0F) * 100.0) / 100.0).toString() + " - " + MetadataUtil.getRatingString(itemView.context, meta.averageRating?.times(2))
|
||||
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_info_24dp)?.apply {
|
||||
setTint(itemView.context.getResourceColor(R.attr.colorAccent))
|
||||
setBounds(0, 0, 20.dpToPx, 20.dpToPx)
|
||||
binding.moreInfo.setCompoundDrawables(this, null, null, null)
|
||||
}
|
||||
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
|
||||
|
||||
listOf(
|
||||
binding.favorites,
|
||||
|
@ -1,24 +0,0 @@
|
||||
package exh.util
|
||||
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
|
||||
class CachedField<T>(private val expiresAfterMs: Long) {
|
||||
@Volatile
|
||||
private var initTime: Long = -1
|
||||
|
||||
@Volatile
|
||||
private var content: T? = null
|
||||
|
||||
private val mutex = Mutex()
|
||||
|
||||
suspend fun obtain(producer: suspend () -> T): T {
|
||||
return mutex.withLock {
|
||||
if (initTime < 0 || System.currentTimeMillis() - initTime > expiresAfterMs) {
|
||||
content = producer()
|
||||
}
|
||||
|
||||
content!!
|
||||
}
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
package exh.util
|
||||
|
||||
/**
|
||||
* Reads entire `JsonObject`s and `JsonArray`s from `JsonReader`s
|
||||
*
|
||||
* @author nulldev
|
||||
*/
|
||||
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonNull
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.stream.JsonReader
|
||||
import com.google.gson.stream.JsonToken
|
||||
import java.math.BigDecimal
|
||||
|
||||
fun JsonReader.nextJsonObject(): JsonObject {
|
||||
beginObject()
|
||||
|
||||
val obj = JsonObject()
|
||||
|
||||
while (hasNext()) {
|
||||
val name = nextName()
|
||||
|
||||
when (peek()) {
|
||||
JsonToken.BEGIN_ARRAY -> obj.add(name, nextJsonArray())
|
||||
JsonToken.BEGIN_OBJECT -> obj.add(name, nextJsonObject())
|
||||
JsonToken.NULL -> {
|
||||
nextNull()
|
||||
obj.add(name, JsonNull.INSTANCE)
|
||||
}
|
||||
JsonToken.BOOLEAN -> obj.addProperty(name, nextBoolean())
|
||||
JsonToken.NUMBER -> obj.addProperty(name, BigDecimal(nextString()))
|
||||
JsonToken.STRING -> obj.addProperty(name, nextString())
|
||||
else -> skipValue()
|
||||
}
|
||||
}
|
||||
|
||||
endObject()
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
fun JsonReader.nextJsonArray(): JsonArray {
|
||||
beginArray()
|
||||
|
||||
val arr = JsonArray()
|
||||
|
||||
while (hasNext()) {
|
||||
when (peek()) {
|
||||
JsonToken.BEGIN_ARRAY -> arr.add(nextJsonArray())
|
||||
JsonToken.BEGIN_OBJECT -> arr.add(nextJsonObject())
|
||||
JsonToken.NULL -> {
|
||||
nextNull()
|
||||
arr.add(JsonNull.INSTANCE)
|
||||
}
|
||||
JsonToken.BOOLEAN -> arr.add(nextBoolean())
|
||||
JsonToken.NUMBER -> arr.add(BigDecimal(nextString()))
|
||||
JsonToken.STRING -> arr.add(nextString())
|
||||
else -> skipValue()
|
||||
}
|
||||
}
|
||||
|
||||
endArray()
|
||||
|
||||
return arr
|
||||
}
|
@ -1,5 +1,11 @@
|
||||
package exh.util
|
||||
|
||||
fun Float.floor(): Int = kotlin.math.floor(this).toInt()
|
||||
import kotlin.math.floor
|
||||
|
||||
fun Double.floor(): Int = kotlin.math.floor(this).toInt()
|
||||
fun Float.floor(): Int = floor(this).toInt()
|
||||
|
||||
fun Double.floor(): Int = floor(this).toInt()
|
||||
|
||||
fun Int.nullIfZero() = if (this == 0) null else this
|
||||
|
||||
fun Long.nullIfZero() = if (this == 0L) null else this
|
||||
|
@ -1,368 +0,0 @@
|
||||
package exh.util
|
||||
|
||||
import android.util.SparseArray
|
||||
import java.util.AbstractMap
|
||||
import java.util.LinkedList
|
||||
|
||||
class NakedTrieNode<T>(val key: Int, var parent: NakedTrieNode<T>?) {
|
||||
val children = SparseArray<NakedTrieNode<T>>(1)
|
||||
var hasData: Boolean = false
|
||||
var data: T? = null
|
||||
|
||||
// Walks in ascending order
|
||||
// Consumer should return true to continue walking, false to stop walking
|
||||
inline fun walk(prefix: String, consumer: (String, T) -> Boolean, leavesOnly: Boolean) {
|
||||
// Special case root
|
||||
if (hasData && (!leavesOnly || children.size() <= 0)) {
|
||||
if (!consumer(prefix, data!! as T)) return
|
||||
}
|
||||
|
||||
val stack = LinkedList<Pair<String, NakedTrieNode<T>>>()
|
||||
SparseArrayValueCollection(children, true).forEach {
|
||||
stack += prefix + it.key.toChar() to it
|
||||
}
|
||||
while (!stack.isEmpty()) {
|
||||
val (key, bottom) = stack.removeLast()
|
||||
SparseArrayValueCollection(bottom.children, true).forEach {
|
||||
stack += key + it.key.toChar() to it
|
||||
}
|
||||
if (bottom.hasData && (!leavesOnly || bottom.children.size() <= 0)) {
|
||||
if (!consumer(key, bottom.data!! as T)) return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getAsNode(key: String): NakedTrieNode<T>? {
|
||||
var current = this
|
||||
for (c in key) {
|
||||
current = current.children.get(c.toInt()) ?: return null
|
||||
if (!current.hasData) return null
|
||||
}
|
||||
return current
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fast, memory efficient and flexible trie implementation with implementation details exposed
|
||||
*/
|
||||
class NakedTrie<T> : MutableMap<String, T> {
|
||||
/**
|
||||
* Returns the number of key/value pairs in the map.
|
||||
*/
|
||||
override var size: Int = 0
|
||||
private set
|
||||
|
||||
/**
|
||||
* Returns `true` if the map is empty (contains no elements), `false` otherwise.
|
||||
*/
|
||||
override fun isEmpty() = size <= 0
|
||||
|
||||
/**
|
||||
* Removes all elements from this map.
|
||||
*/
|
||||
override fun clear() {
|
||||
root.children.clear()
|
||||
root.hasData = false
|
||||
root.data = null
|
||||
size = 0
|
||||
}
|
||||
|
||||
val root = NakedTrieNode<T>(-1, null)
|
||||
private var version: Long = 0
|
||||
|
||||
override fun put(key: String, value: T): T? {
|
||||
// Traverse to node location in tree, making parent nodes if required
|
||||
var current = root
|
||||
for (c in key) {
|
||||
val castedC = c.toInt()
|
||||
var node = current.children.get(castedC)
|
||||
if (node == null) {
|
||||
node = NakedTrieNode(castedC, current)
|
||||
current.children.put(castedC, node)
|
||||
}
|
||||
current = node
|
||||
}
|
||||
|
||||
// Add data to node or replace existing data
|
||||
val previous = if (current.hasData) {
|
||||
current.data
|
||||
} else {
|
||||
current.hasData = true
|
||||
size++
|
||||
null
|
||||
}
|
||||
current.data = value
|
||||
|
||||
version++
|
||||
|
||||
return previous
|
||||
}
|
||||
|
||||
override fun get(key: String): T? {
|
||||
val current = getAsNode(key) ?: return null
|
||||
return if (current.hasData) current.data else null
|
||||
}
|
||||
|
||||
fun getAsNode(key: String): NakedTrieNode<T>? {
|
||||
return root.getAsNode(key)
|
||||
}
|
||||
|
||||
override fun containsKey(key: String): Boolean {
|
||||
var current = root
|
||||
for (c in key) {
|
||||
current = current.children.get(c.toInt()) ?: return false
|
||||
if (!current.hasData) return false
|
||||
}
|
||||
return current.hasData
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified key and its corresponding value from this map.
|
||||
*
|
||||
* @return the previous value associated with the key, or `null` if the key was not present in the map.
|
||||
*/
|
||||
override fun remove(key: String): T? {
|
||||
// Traverse node tree while keeping track of the nodes we have visited
|
||||
val nodeStack = LinkedList<NakedTrieNode<T>>()
|
||||
for (c in key) {
|
||||
val bottomOfStack = nodeStack.last
|
||||
val current = bottomOfStack.children.get(c.toInt()) ?: return null
|
||||
if (!current.hasData) return null
|
||||
nodeStack.add(bottomOfStack)
|
||||
}
|
||||
|
||||
// Mark node as having no data
|
||||
val bottomOfStack = nodeStack.last
|
||||
bottomOfStack.hasData = false
|
||||
val oldData = bottomOfStack.data
|
||||
bottomOfStack.data = null // Clear data field for GC
|
||||
|
||||
// Remove nodes that we visited that are useless
|
||||
for (curBottom in nodeStack.descendingIterator()) {
|
||||
val parent = curBottom.parent ?: break
|
||||
if (!curBottom.hasData && curBottom.children.size() <= 0) {
|
||||
// No data or child nodes, this node is useless, discard
|
||||
parent.children.remove(curBottom.key)
|
||||
} else break
|
||||
}
|
||||
|
||||
version++
|
||||
size--
|
||||
|
||||
return oldData
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates this map with key/value pairs from the specified map [from].
|
||||
*/
|
||||
override fun putAll(from: Map<out String, T>) {
|
||||
// No way to optimize this so yeah...
|
||||
from.forEach { (s, u) ->
|
||||
put(s, u)
|
||||
}
|
||||
}
|
||||
|
||||
// Walks in ascending order
|
||||
// Consumer should return true to continue walking, false to stop walking
|
||||
inline fun walk(consumer: (String, T) -> Boolean) {
|
||||
walk(consumer, false)
|
||||
}
|
||||
|
||||
// Walks in ascending order
|
||||
// Consumer should return true to continue walking, false to stop walking
|
||||
inline fun walk(consumer: (String, T) -> Boolean, leavesOnly: Boolean) {
|
||||
root.walk("", consumer, leavesOnly)
|
||||
}
|
||||
|
||||
fun getOrPut(key: String, producer: () -> T): T {
|
||||
// Traverse to node location in tree, making parent nodes if required
|
||||
var current = root
|
||||
for (c in key) {
|
||||
val castedC = c.toInt()
|
||||
var node = current.children.get(castedC)
|
||||
if (node == null) {
|
||||
node = NakedTrieNode(castedC, current)
|
||||
current.children.put(castedC, node)
|
||||
}
|
||||
current = node
|
||||
}
|
||||
|
||||
// Add data to node or replace existing data
|
||||
if (!current.hasData) {
|
||||
current.hasData = true
|
||||
current.data = producer()
|
||||
size++
|
||||
version++
|
||||
}
|
||||
|
||||
return current.data!!
|
||||
}
|
||||
|
||||
// Includes root
|
||||
fun subMap(prefix: String, leavesOnly: Boolean = false): Map<String, T> {
|
||||
val node = getAsNode(prefix) ?: return emptyMap()
|
||||
|
||||
return object : Map<String, T> {
|
||||
/**
|
||||
* Returns a read-only [Set] of all key/value pairs in this map.
|
||||
*/
|
||||
override val entries: Set<Map.Entry<String, T>>
|
||||
get() {
|
||||
val out = mutableSetOf<Map.Entry<String, T>>()
|
||||
node.walk(
|
||||
"",
|
||||
{ k, v ->
|
||||
out.add(AbstractMap.SimpleImmutableEntry(k, v))
|
||||
true
|
||||
},
|
||||
leavesOnly
|
||||
)
|
||||
return out
|
||||
}
|
||||
/**
|
||||
* Returns a read-only [Set] of all keys in this map.
|
||||
*/
|
||||
override val keys: Set<String>
|
||||
get() {
|
||||
val out = mutableSetOf<String>()
|
||||
node.walk(
|
||||
"",
|
||||
{ k, _ ->
|
||||
out.add(k)
|
||||
true
|
||||
},
|
||||
leavesOnly
|
||||
)
|
||||
return out
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of key/value pairs in the map.
|
||||
*/
|
||||
override val size: Int get() {
|
||||
var s = 0
|
||||
node.walk("", { _, _ -> s++; true }, leavesOnly)
|
||||
return s
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a read-only [Collection] of all values in this map. Note that this collection may contain duplicate values.
|
||||
*/
|
||||
override val values: Collection<T>
|
||||
get() {
|
||||
val out = mutableSetOf<T>()
|
||||
node.walk(
|
||||
"",
|
||||
{ _, v ->
|
||||
out.add(v)
|
||||
true
|
||||
},
|
||||
leavesOnly
|
||||
)
|
||||
return out
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if the map contains the specified [key].
|
||||
*/
|
||||
override fun containsKey(key: String): Boolean {
|
||||
if (!key.startsWith(prefix)) return false
|
||||
|
||||
val childNode = node.getAsNode(key.removePrefix(prefix)) ?: return false
|
||||
return childNode.hasData && (!leavesOnly || childNode.children.size() <= 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if the map maps one or more keys to the specified [value].
|
||||
*/
|
||||
override fun containsValue(value: T): Boolean {
|
||||
node.walk(
|
||||
"",
|
||||
{ _, v ->
|
||||
if (v == value) return true
|
||||
true
|
||||
},
|
||||
leavesOnly
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value corresponding to the given [key], or `null` if such a key is not present in the map.
|
||||
*/
|
||||
override fun get(key: String): T? {
|
||||
if (!key.startsWith(prefix)) return null
|
||||
|
||||
val childNode = node.getAsNode(key.removePrefix(prefix)) ?: return null
|
||||
if (!childNode.hasData || (leavesOnly && childNode.children.size() > 0)) return null
|
||||
return childNode.data
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if the map is empty (contains no elements), `false` otherwise.
|
||||
*/
|
||||
override fun isEmpty(): Boolean {
|
||||
if (node.children.size() <= 0 && !root.hasData) return true
|
||||
if (!leavesOnly) return false
|
||||
node.walk("", { _, _ -> return false }, leavesOnly)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Slow methods below
|
||||
|
||||
/**
|
||||
* Returns `true` if the map maps one or more keys to the specified [value].
|
||||
*/
|
||||
override fun containsValue(value: T): Boolean {
|
||||
walk { _, t ->
|
||||
if (t == value) {
|
||||
return true
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [MutableSet] of all key/value pairs in this map.
|
||||
*/
|
||||
override val entries: MutableSet<MutableMap.MutableEntry<String, T>>
|
||||
get() = FakeMutableSet.fromSet(
|
||||
mutableSetOf<MutableMap.MutableEntry<String, T>>().apply {
|
||||
walk { k, v ->
|
||||
this += FakeMutableEntry.fromPair(k, v)
|
||||
true
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Returns a [MutableSet] of all keys in this map.
|
||||
*/
|
||||
override val keys: MutableSet<String>
|
||||
get() = FakeMutableSet.fromSet(
|
||||
mutableSetOf<String>().apply {
|
||||
walk { k, _ ->
|
||||
this += k
|
||||
true
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Returns a [MutableCollection] of all values in this map. Note that this collection may contain duplicate values.
|
||||
*/
|
||||
override val values: MutableCollection<T>
|
||||
get() = FakeMutableCollection.fromCollection(
|
||||
mutableListOf<T>().apply {
|
||||
walk { _, v ->
|
||||
this += v
|
||||
true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
@ -14,7 +14,7 @@ private val galleryAdder by lazy {
|
||||
/**
|
||||
* A version of fetchSearchManga that supports URL importing
|
||||
*/
|
||||
fun UrlImportableSource.urlImportFetchSearchManga(context: Context, query: String, fail: () -> Observable<MangasPage>) =
|
||||
fun UrlImportableSource.urlImportFetchSearchManga(context: Context, query: String, fail: () -> Observable<MangasPage>): Observable<MangasPage> =
|
||||
when {
|
||||
query.startsWith("http://") || query.startsWith("https://") -> {
|
||||
Observable.fromCallable {
|
||||
|
@ -10,7 +10,7 @@ import exh.metadata.metadata.base.RaisedTag
|
||||
import exh.nHentaiSourceIds
|
||||
import java.util.Locale
|
||||
|
||||
class SourceTagsUtil {
|
||||
object SourceTagsUtil {
|
||||
fun getWrappedTag(sourceId: Long, namespace: String? = null, tag: String? = null, fullTag: String? = null): String? {
|
||||
return if (sourceId == EXH_SOURCE_ID || sourceId == EH_SOURCE_ID || sourceId in nHentaiSourceIds || sourceId in hitomiSourceIds) {
|
||||
val parsed = if (fullTag != null) parseTag(fullTag) else if (namespace != null && tag != null) RaisedTag(namespace, tag, TAG_TYPE_DEFAULT) else null
|
||||
@ -47,8 +47,6 @@ class SourceTagsUtil {
|
||||
} else {
|
||||
"$namespace:$tag"
|
||||
}
|
||||
companion object {
|
||||
fun Manga.getRaisedTags(genres: List<String>? = null): List<RaisedTag>? = (genres ?: this.getGenres())?.map { parseTag(it) }
|
||||
|
||||
fun parseTag(tag: String) = RaisedTag(
|
||||
(
|
||||
@ -95,4 +93,7 @@ class SourceTagsUtil {
|
||||
|
||||
private const val TAG_TYPE_DEFAULT = 1
|
||||
}
|
||||
|
||||
fun Manga.getRaisedTags(genres: List<String>? = null): List<RaisedTag>? = (genres ?: this.getGenres())?.map {
|
||||
SourceTagsUtil.parseTag(it)
|
||||
}
|
||||
|
@ -1,73 +0,0 @@
|
||||
package exh.util
|
||||
|
||||
import android.util.SparseArray
|
||||
import java.util.AbstractMap
|
||||
|
||||
class SparseArrayKeyCollection(val sparseArray: SparseArray<out Any?>, var reverse: Boolean = false) : AbstractCollection<Int>() {
|
||||
override val size get() = sparseArray.size()
|
||||
|
||||
override fun iterator() = object : Iterator<Int> {
|
||||
private var index: Int = 0
|
||||
|
||||
/**
|
||||
* Returns `true` if the iteration has more elements.
|
||||
*/
|
||||
override fun hasNext() = index < sparseArray.size()
|
||||
|
||||
/**
|
||||
* Returns the next element in the iteration.
|
||||
*/
|
||||
override fun next(): Int {
|
||||
var idx = index++
|
||||
if (reverse) idx = sparseArray.size() - 1 - idx
|
||||
return sparseArray.keyAt(idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SparseArrayValueCollection<E>(val sparseArray: SparseArray<E>, var reverse: Boolean = false) : AbstractCollection<E>() {
|
||||
override val size get() = sparseArray.size()
|
||||
|
||||
override fun iterator() = object : Iterator<E> {
|
||||
private var index: Int = 0
|
||||
|
||||
/**
|
||||
* Returns `true` if the iteration has more elements.
|
||||
*/
|
||||
override fun hasNext() = index < sparseArray.size()
|
||||
|
||||
/**
|
||||
* Returns the next element in the iteration.
|
||||
*/
|
||||
override fun next(): E {
|
||||
var idx = index++
|
||||
if (reverse) idx = sparseArray.size() - 1 - idx
|
||||
return sparseArray.valueAt(idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SparseArrayCollection<E>(val sparseArray: SparseArray<E>, var reverse: Boolean = false) : AbstractCollection<Map.Entry<Int, E>>() {
|
||||
override val size get() = sparseArray.size()
|
||||
|
||||
override fun iterator() = object : Iterator<Map.Entry<Int, E>> {
|
||||
private var index: Int = 0
|
||||
|
||||
/**
|
||||
* Returns `true` if the iteration has more elements.
|
||||
*/
|
||||
override fun hasNext() = index < sparseArray.size()
|
||||
|
||||
/**
|
||||
* Returns the next element in the iteration.
|
||||
*/
|
||||
override fun next(): Map.Entry<Int, E> {
|
||||
var idx = index++
|
||||
if (reverse) idx = sparseArray.size() - 1 - idx
|
||||
return AbstractMap.SimpleImmutableEntry(
|
||||
sparseArray.keyAt(idx),
|
||||
sparseArray.valueAt(idx)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -5,9 +5,7 @@ import com.google.android.material.chip.Chip
|
||||
import com.google.android.material.chip.ChipGroup
|
||||
import exh.EH_SOURCE_ID
|
||||
import exh.EXH_SOURCE_ID
|
||||
import exh.metadata.metadata.EHentaiSearchMetadata.Companion.TAG_TYPE_LIGHT
|
||||
import exh.metadata.metadata.EHentaiSearchMetadata.Companion.TAG_TYPE_NORMAL
|
||||
import exh.metadata.metadata.EHentaiSearchMetadata.Companion.TAG_TYPE_WEAK
|
||||
import exh.metadata.metadata.EHentaiSearchMetadata
|
||||
|
||||
/**
|
||||
* Replaces chips in a ChipGroup.
|
||||
@ -29,7 +27,7 @@ fun ChipGroup.setChipsExtended(items: List<String>?, onClick: (item: String) ->
|
||||
fun makeSearchChip(item: String, onClick: (item: String) -> Unit = {}, onLongClick: (item: String) -> Unit = {}, sourceId: Long, context: Context, namespace: String? = null, type: Int? = null): Chip {
|
||||
return Chip(context).apply {
|
||||
text = item
|
||||
val search = (if (namespace != null) SourceTagsUtil().getWrappedTag(sourceId, namespace = namespace, tag = item) else SourceTagsUtil().getWrappedTag(sourceId, fullTag = item)) ?: item
|
||||
val search = (if (namespace != null) SourceTagsUtil.getWrappedTag(sourceId, namespace = namespace, tag = item) else SourceTagsUtil.getWrappedTag(sourceId, fullTag = item)) ?: item
|
||||
setOnClickListener { onClick(search) }
|
||||
setOnLongClickListener {
|
||||
onLongClick(search)
|
||||
@ -37,9 +35,9 @@ fun makeSearchChip(item: String, onClick: (item: String) -> Unit = {}, onLongCli
|
||||
}
|
||||
if (sourceId == EXH_SOURCE_ID || sourceId == EH_SOURCE_ID) {
|
||||
chipStrokeWidth = when (type) {
|
||||
TAG_TYPE_NORMAL -> 5F
|
||||
TAG_TYPE_LIGHT -> 3F
|
||||
TAG_TYPE_WEAK -> 0F
|
||||
EHentaiSearchMetadata.TAG_TYPE_NORMAL -> 5F
|
||||
EHentaiSearchMetadata.TAG_TYPE_LIGHT -> 3F
|
||||
EHentaiSearchMetadata.TAG_TYPE_WEAK -> 0F
|
||||
else -> chipStrokeWidth
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +0,0 @@
|
||||
package exh.util
|
||||
|
||||
import android.content.Context
|
||||
|
||||
fun dpToPx(context: Context, dp: Int): Int {
|
||||
val scale = context.resources.displayMetrics.density
|
||||
return (dp * scale + 0.5f).toInt()
|
||||
}
|
@ -10,10 +10,11 @@ import com.afollestad.materialdialogs.customview.customView
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.online.all.MangaDex
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import eu.kanade.tachiyomi.widget.preference.LoginDialogPreference
|
||||
import exh.md.utils.MdUtil
|
||||
import exh.source.getMainSource
|
||||
import kotlinx.android.synthetic.main.pref_site_login_two_factor_auth.view.login
|
||||
import kotlinx.android.synthetic.main.pref_site_login_two_factor_auth.view.password
|
||||
import kotlinx.android.synthetic.main.pref_site_login_two_factor_auth.view.two_factor_check
|
||||
@ -29,7 +30,7 @@ import uy.kohesive.injekt.api.get
|
||||
|
||||
class MangadexLoginDialog(bundle: Bundle? = null) : LoginDialogPreference(bundle = bundle) {
|
||||
|
||||
val source by lazy { MdUtil.getEnabledMangaDex() }
|
||||
val source = Injekt.get<SourceManager>().get(args.getLong("key", 0))?.getMainSource() as? MangaDex
|
||||
|
||||
val service = Injekt.get<TrackManager>().mdList
|
||||
|
||||
|
@ -7,17 +7,21 @@ import com.afollestad.materialdialogs.MaterialDialog
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.online.all.MangaDex
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
import eu.kanade.tachiyomi.util.lang.launchNow
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import exh.md.utils.MdUtil
|
||||
import exh.source.getMainSource
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class MangadexLogoutDialog(bundle: Bundle? = null) : DialogController(bundle) {
|
||||
|
||||
val source by lazy { MdUtil.getEnabledMangaDex() }
|
||||
val source = Injekt.get<SourceManager>().get(args.getLong("key", 0))?.getMainSource() as? MangaDex
|
||||
|
||||
val trackManager: TrackManager by injectLazy()
|
||||
|
||||
|
@ -1,93 +0,0 @@
|
||||
package org.vepta.vdm
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
/**
|
||||
* Simple cursor for use on byte arrays
|
||||
* @author nulldev
|
||||
*/
|
||||
class ByteCursor(val content: ByteArray) {
|
||||
var index = -1
|
||||
private set
|
||||
private var mark = -1
|
||||
|
||||
fun mark() {
|
||||
mark = index
|
||||
}
|
||||
|
||||
fun jumpToMark() {
|
||||
index = mark
|
||||
}
|
||||
|
||||
fun jumpToIndex(index: Int) {
|
||||
this.index = index
|
||||
}
|
||||
|
||||
fun next(): Byte {
|
||||
return content[++index]
|
||||
}
|
||||
|
||||
fun next(count: Int): ByteArray {
|
||||
val res = content.sliceArray(index + 1..index + count)
|
||||
skip(count)
|
||||
return res
|
||||
}
|
||||
|
||||
// Used to perform conversions
|
||||
private fun byteBuffer(count: Int): ByteBuffer {
|
||||
return ByteBuffer.wrap(next(count))
|
||||
}
|
||||
|
||||
// Epic hack to get an unsigned short properly...
|
||||
fun fakeNextShortInt(): Int = ByteBuffer
|
||||
.wrap(arrayOf(0x00, 0x00, *next(2).toTypedArray()).toByteArray())
|
||||
.getInt(0)
|
||||
|
||||
// fun nextShort(): Short = byteBuffer(2).getShort(0)
|
||||
fun nextInt(): Int = byteBuffer(4).getInt(0)
|
||||
fun nextLong(): Long = byteBuffer(8).getLong(0)
|
||||
fun nextFloat(): Float = byteBuffer(4).getFloat(0)
|
||||
fun nextDouble(): Double = byteBuffer(8).getDouble(0)
|
||||
|
||||
fun skip(count: Int) {
|
||||
index += count
|
||||
}
|
||||
|
||||
fun expect(vararg bytes: Byte) {
|
||||
if (bytes.size > remaining()) {
|
||||
throw IllegalStateException("Unexpected end of content!")
|
||||
}
|
||||
|
||||
for (i in 0..bytes.lastIndex) {
|
||||
val expected = bytes[i]
|
||||
val actual = content[index + i + 1]
|
||||
|
||||
if (expected != actual) {
|
||||
throw IllegalStateException("Unexpected content (expected: $expected, actual: $actual)!")
|
||||
}
|
||||
}
|
||||
|
||||
index += bytes.size
|
||||
}
|
||||
|
||||
fun checkEqual(vararg bytes: Byte): Boolean {
|
||||
if (bytes.size > remaining()) {
|
||||
return false
|
||||
}
|
||||
|
||||
for (i in 0..bytes.lastIndex) {
|
||||
val expected = bytes[i]
|
||||
val actual = content[index + i + 1]
|
||||
|
||||
if (expected != actual) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun atEnd() = index >= content.size - 1
|
||||
|
||||
fun remaining() = content.size - index - 1
|
||||
}
|
@ -34,20 +34,18 @@ class FilterSerializer {
|
||||
)
|
||||
|
||||
fun serialize(filters: FilterList) = buildJsonArray {
|
||||
filters.forEach {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
add(serialize(it as Filter<Any?>))
|
||||
filters.filterIsInstance<Filter<Any?>>().forEach {
|
||||
add(serialize(it))
|
||||
}
|
||||
}
|
||||
|
||||
fun serialize(filter: Filter<Any?>): JsonObject {
|
||||
for (serializer in serializers) {
|
||||
if (filter::class.isSubclassOf(serializer.clazz)) {
|
||||
// TODO Not sure how to deal with the mess of types here
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
serializer as Serializer<Filter<Any?>>
|
||||
|
||||
return buildJsonObject {
|
||||
return serializers
|
||||
.filterIsInstance<Serializer<Filter<Any?>>>()
|
||||
.firstOrNull {
|
||||
filter::class.isSubclassOf(it.clazz)
|
||||
}?.let { serializer ->
|
||||
buildJsonObject {
|
||||
with(serializer) { serialize(filter) }
|
||||
|
||||
val classMappings = mutableListOf<Pair<String, Any>>()
|
||||
@ -66,27 +64,22 @@ class FilterSerializer {
|
||||
|
||||
put(TYPE, serializer.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
throw IllegalArgumentException("Cannot serialize this Filter object!")
|
||||
} ?: throw IllegalArgumentException("Cannot serialize this Filter object!")
|
||||
}
|
||||
|
||||
fun deserialize(filters: FilterList, json: JsonArray) {
|
||||
filters.zip(json).forEach { (filter, obj) ->
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
deserialize(filter as Filter<Any?>, obj.jsonObject)
|
||||
filters.filterIsInstance<Filter<Any?>>().zip(json).forEach { (filter, obj) ->
|
||||
deserialize(filter, obj.jsonObject)
|
||||
}
|
||||
}
|
||||
|
||||
fun deserialize(filter: Filter<Any?>, json: JsonObject) {
|
||||
val serializer = serializers.find {
|
||||
val serializer = serializers
|
||||
.filterIsInstance<Serializer<Filter<Any?>>>()
|
||||
.firstOrNull {
|
||||
it.type == json[TYPE]!!.jsonPrimitive.content
|
||||
} ?: throw IllegalArgumentException("Cannot deserialize this type!")
|
||||
|
||||
// TODO Not sure how to deal with the mess of types here
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
serializer as Serializer<Filter<Any?>>
|
||||
|
||||
serializer.deserialize(json, filter)
|
||||
|
||||
serializer.mappings().forEach {
|
||||
|
Loading…
x
Reference in New Issue
Block a user