From 9cba544ffdc4d42e1fe0f5eaa5410c9acce86031 Mon Sep 17 00:00:00 2001 From: Jobobby04 Date: Tue, 27 Oct 2020 19:52:32 -0400 Subject: [PATCH] Refactor and cleanup a bunch of code --- .../data/backup/full/FullBackupManager.kt | 2 +- .../data/library/LibraryUpdateService.kt | 41 +- .../tachiyomi/source/online/all/EHentai.kt | 51 ++- .../tachiyomi/source/online/all/NHentai.kt | 2 +- .../source/browse/BrowseSourceController.kt | 2 +- .../browse/SourceEnhancedEHentaiListHolder.kt | 7 +- .../browse/source/browse/SourceFilterSheet.kt | 2 +- .../tachiyomi/ui/library/LibraryItem.kt | 13 +- .../tachiyomi/ui/manga/MangaController.kt | 2 +- .../tachiyomi/ui/manga/MangaPresenter.kt | 2 +- .../ui/manga/chapter/ChapterHolder.kt | 4 +- .../ui/manga/chapter/ChaptersSettingsSheet.kt | 2 +- .../ui/manga/info/MangaInfoHeaderAdapter.kt | 12 +- .../ui/manga/info/MangaInfoItemAdapter.kt | 4 +- .../tachiyomi/ui/reader/ReaderPresenter.kt | 2 +- .../ui/setting/SettingsMangaDexController.kt | 8 +- app/src/main/java/exh/GalleryAdder.kt | 2 +- app/src/main/java/exh/debug/DebugFunctions.kt | 3 +- .../md/follows/MangaDexFollowsPresenter.kt | 2 +- .../java/exh/md/handlers/ApiMangaParser.kt | 9 +- .../java/exh/md/handlers/FollowsHandler.kt | 45 ++- .../main/java/exh/md/handlers/MangaHandler.kt | 10 +- .../md/similar/ui/MangaDexSimilarPresenter.kt | 2 +- app/src/main/java/exh/md/utils/MdUtil.kt | 17 +- .../main/java/exh/metadata/MetadataUtil.kt | 146 ++++--- .../metadata/EHentaiSearchMetadata.kt | 45 ++- .../metadata/EightMusesSearchMetadata.kt | 6 +- .../metadata/HBrowseSearchMetadata.kt | 12 +- .../metadata/HentaiCafeSearchMetadata.kt | 10 +- .../metadata/metadata/HitomiSearchMetadata.kt | 40 +- .../metadata/MangaDexSearchMetadata.kt | 36 +- .../metadata/NHentaiSearchMetadata.kt | 27 +- .../metadata/PervEdenSearchMetadata.kt | 20 +- .../metadata/PururinSearchMetadata.kt | 20 +- .../metadata/TsuminoSearchMetadata.kt | 30 +- app/src/main/java/exh/search/Text.kt | 5 +- .../java/exh/source/EnhancedHttpSource.kt | 35 +- .../ui/captcha/AutoSolvingWebViewClient.kt | 3 +- .../exh/ui/metadata/MetadataViewController.kt | 2 +- .../adapters/EHentaiDescriptionAdapter.kt | 76 +--- .../adapters/EightMusesDescriptionAdapter.kt | 10 +- .../adapters/HBrowseDescriptionAdapter.kt | 16 +- .../adapters/HentaiCafeDescriptionAdapter.kt | 10 +- .../adapters/HitomiDescriptionAdapter.kt | 41 +- .../adapters/MangaDexDescriptionAdapter.kt | 33 +- .../adapters/NHentaiDescriptionAdapter.kt | 60 +-- .../adapters/PervEdenDescriptionAdapter.kt | 50 +-- .../adapters/PururinDescriptionAdapter.kt | 67 +--- .../adapters/TsuminoDescriptionAdapter.kt | 62 +-- app/src/main/java/exh/util/CachedField.kt | 24 -- .../java/exh/util/JsonReaderObjectReader.kt | 66 ---- app/src/main/java/exh/util/Math.kt | 10 +- app/src/main/java/exh/util/NakedTrie.kt | 368 ------------------ app/src/main/java/exh/util/SearchOverride.kt | 2 +- app/src/main/java/exh/util/SourceTagsUtil.kt | 89 ++--- .../java/exh/util/SparseArrayCollection.kt | 73 ---- app/src/main/java/exh/util/ViewExtensions.kt | 12 +- app/src/main/java/exh/util/ViewUtil.kt | 8 - .../widget/preference/MangadexLoginDialog.kt | 5 +- .../widget/preference/MangadexLogoutDialog.kt | 8 +- app/src/main/java/org/vepta/vdm/ByteCursor.kt | 93 ----- .../api/http/serializer/FilterSerializer.kt | 39 +- 62 files changed, 521 insertions(+), 1384 deletions(-) delete mode 100644 app/src/main/java/exh/util/CachedField.kt delete mode 100644 app/src/main/java/exh/util/JsonReaderObjectReader.kt delete mode 100644 app/src/main/java/exh/util/NakedTrie.kt delete mode 100644 app/src/main/java/exh/util/SparseArrayCollection.kt delete mode 100644 app/src/main/java/exh/util/ViewUtil.kt delete mode 100644 app/src/main/java/org/vepta/vdm/ByteCursor.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt index 498bf795a..376352252 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt @@ -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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt index cee81b902..a04134325 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt @@ -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, List>> { - val source = sourceManager.getOrStub(manga.source) + val source = sourceManager.getOrStub(manga.source).getMainSource() // Update manga details metadata in the background if (preferences.autoUpdateMetadata()) { @@ -447,21 +447,6 @@ class LibraryUpdateService( .subscribe() } - // SY --> - if (source.getMainSource() is MangaDex && trackManager.mdList.isLogged) { - try { - 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() - } - } catch (e: Exception) { - XLog.e(e) - } - } - // SY <-- - return ( /* SY --> */ if (source is MergedSource) runBlocking { source.fetchChaptersAndSync(manga, false).asObservable() } else /* SY <-- */ source.fetchChapterList(manga) @@ -469,12 +454,16 @@ class LibraryUpdateService( // 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() + if (source is MangaDex && trackManager.mdList.isLogged) { + try { + 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() + } + } catch (e: Exception) { + XLog.e(e) } } } @@ -548,7 +537,7 @@ class LibraryUpdateService( // filter all follows from Mangadex and only add reading or rereading manga to library private fun syncFollows(): Observable { 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 <-- diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt index 2e186ed07..4b1b20130 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt @@ -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() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/NHentai.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/NHentai.kt index 434f6827a..9cd0c29d6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/NHentai.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/NHentai.kt @@ -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)) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt index 805a0cd99..601339f09 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt @@ -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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceEnhancedEHentaiListHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceEnhancedEHentaiListHolder.kt index 9ff22bbc1..0eac7f7de 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceEnhancedEHentaiListHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceEnhancedEHentaiListHolder.kt @@ -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) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterSheet.kt index 880c20318..8dc45d1ae 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterSheet.kt @@ -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, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt index 56823d6da..8e07a0a29 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt @@ -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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt index 2250e0150..d0107f5bb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt @@ -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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt index fd5e204a2..850ce0d61 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt @@ -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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterHolder.kt index 6f349686c..65e36d997 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterHolder.kt @@ -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) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt index 3b2fa8152..cbc78c84b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt @@ -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, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt index a76a721a9..ae12afa98 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt @@ -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) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoItemAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoItemAdapter.kt index fda384abe..8e4d74321 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoItemAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoItemAdapter.kt @@ -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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt index 59397657c..c9a2ea014 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt @@ -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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMangaDexController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMangaDexController.kt index aedee2a29..2af5a0d78 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMangaDexController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMangaDexController.kt @@ -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) diff --git a/app/src/main/java/exh/GalleryAdder.kt b/app/src/main/java/exh/GalleryAdder.kt index 8541ae83b..e9cb10082 100755 --- a/app/src/main/java/exh/GalleryAdder.kt +++ b/app/src/main/java/exh/GalleryAdder.kt @@ -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 diff --git a/app/src/main/java/exh/debug/DebugFunctions.kt b/app/src/main/java/exh/debug/DebugFunctions.kt index c200b7de8..2399fe2a7 100644 --- a/app/src/main/java/exh/debug/DebugFunctions.kt +++ b/app/src/main/java/exh/debug/DebugFunctions.kt @@ -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() diff --git a/app/src/main/java/exh/md/follows/MangaDexFollowsPresenter.kt b/app/src/main/java/exh/md/follows/MangaDexFollowsPresenter.kt index 23cf7fcc3..367113d2b 100644 --- a/app/src/main/java/exh/md/follows/MangaDexFollowsPresenter.kt +++ b/app/src/main/java/exh/md/follows/MangaDexFollowsPresenter.kt @@ -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. diff --git a/app/src/main/java/exh/md/handlers/ApiMangaParser.kt b/app/src/main/java/exh/md/handlers/ApiMangaParser.kt index f7d0e2d0e..f11a83f98 100644 --- a/app/src/main/java/exh/md/handlers/ApiMangaParser.kt +++ b/app/src/main/java/exh/md/handlers/ApiMangaParser.kt @@ -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) { 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) { } } 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() } diff --git a/app/src/main/java/exh/md/handlers/FollowsHandler.kt b/app/src/main/java/exh/md/handlers/FollowsHandler.kt index 12ecb66d9..1985b20cf 100644 --- a/app/src/main/java/exh/md/handlers/FollowsHandler.kt +++ b/app/src/main/java/exh/md/handlers/FollowsHandler.kt @@ -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> { return withContext(Dispatchers.IO) { val listManga = mutableListOf>() - 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 diff --git a/app/src/main/java/exh/md/handlers/MangaHandler.kt b/app/src/main/java/exh/md/handlers/MangaHandler.kt index c1f3f414a..8467c3451 100644 --- a/app/src/main/java/exh/md/handlers/MangaHandler.kt +++ b/app/src/main/java/exh/md/handlers/MangaHandler.kt @@ -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> { 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 { return withContext(Dispatchers.IO) { - val response = client.newCall(apiRequest(manga)).execute() + val response = client.newCall(apiRequest(manga)).await() ApiMangaParser(langs).chapterListParse(response) } } diff --git a/app/src/main/java/exh/md/similar/ui/MangaDexSimilarPresenter.kt b/app/src/main/java/exh/md/similar/ui/MangaDexSimilarPresenter.kt index dfffee18a..17a7e978a 100644 --- a/app/src/main/java/exh/md/similar/ui/MangaDexSimilarPresenter.kt +++ b/app/src/main/java/exh/md/similar/ui/MangaDexSimilarPresenter.kt @@ -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 /** diff --git a/app/src/main/java/exh/md/utils/MdUtil.kt b/app/src/main/java/exh/md/utils/MdUtil.kt index 691822ff4..cb61b4299 100644 --- a/app/src/main/java/exh/md/utils/MdUtil.kt +++ b/app/src/main/java/exh/md/utils/MdUtil.kt @@ -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() .filter { it.lang in languages } .filterNot { it.id.toString() in disabledSourceIds } - .filterIsInstance(MangaDex::class.java) } fun mapMdIdToMangaUrl(id: Int) = "/manga/$id/" diff --git a/app/src/main/java/exh/metadata/MetadataUtil.kt b/app/src/main/java/exh/metadata/MetadataUtil.kt index 36b834b81..25a6df1fa 100755 --- a/app/src/main/java/exh/metadata/MetadataUtil.kt +++ b/app/src/main/java/exh/metadata/MetadataUtil.kt @@ -1,62 +1,118 @@ 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 */ -fun humanReadableByteCount(bytes: Long, si: Boolean): String { - val unit = if (si) 1000 else 1024 - if (bytes < unit) return "$bytes B" - val exp = (ln(bytes.toDouble()) / ln(unit.toDouble())).toInt() - val pre = (if (si) "kMGTPE" else "KMGTPE")[exp - 1] + if (si) "" else "i" - return String.format("%.1f %sB", bytes / unit.toDouble().pow(exp.toDouble()), pre) -} - -private const val KB_FACTOR: Long = 1000 -private const val KIB_FACTOR: Long = 1024 -private const val MB_FACTOR = 1000 * KB_FACTOR -private const val MIB_FACTOR = 1024 * KIB_FACTOR -private const val GB_FACTOR = 1000 * MB_FACTOR -private const val GIB_FACTOR = 1024 * MIB_FACTOR - -fun parseHumanReadableByteCount(arg0: String): Double? { - val spaceNdx = arg0.indexOf(" ") - val ret = java.lang.Double.parseDouble(arg0.substring(0, spaceNdx)) - when (arg0.substring(spaceNdx + 1)) { - "GB" -> return ret * GB_FACTOR - "GiB" -> return ret * GIB_FACTOR - "MB" -> return ret * MB_FACTOR - "MiB" -> return ret * MIB_FACTOR - "KB" -> return ret * KB_FACTOR - "KiB" -> return ret * KIB_FACTOR +object MetadataUtil { + fun humanReadableByteCount(bytes: Long, si: Boolean): String { + val unit = if (si) 1000 else 1024 + if (bytes < unit) return "$bytes B" + val exp = (ln(bytes.toDouble()) / ln(unit.toDouble())).toInt() + val pre = (if (si) "kMGTPE" else "KMGTPE")[exp - 1] + if (si) "" else "i" + return String.format("%.1f %sB", bytes / unit.toDouble().pow(exp.toDouble()), pre) } - return null + + private const val KB_FACTOR: Long = 1000 + private const val KIB_FACTOR: Long = 1024 + private const val MB_FACTOR = 1000 * KB_FACTOR + private const val MIB_FACTOR = 1024 * KIB_FACTOR + private const val GB_FACTOR = 1000 * MB_FACTOR + private const val GIB_FACTOR = 1024 * MIB_FACTOR + + fun parseHumanReadableByteCount(arg0: String): Double? { + val spaceNdx = arg0.indexOf(" ") + val ret = java.lang.Double.parseDouble(arg0.substring(0, spaceNdx)) + when (arg0.substring(spaceNdx + 1)) { + "GB" -> return ret * GB_FACTOR + "GiB" -> return ret * GIB_FACTOR + "MB" -> return ret * MB_FACTOR + "MiB" -> return ret * MIB_FACTOR + "KB" -> return ret * KB_FACTOR + "KiB" -> return ret * KIB_FACTOR + } + return null + } + + val ONGOING_SUFFIX = arrayOf( + "[ongoing]", + "(ongoing)", + "{ongoing}", + "", + "ongoing", + "[incomplete]", + "(incomplete)", + "{incomplete}", + "", + "incomplete", + "[wip]", + "(wip)", + "{wip}", + "", + "wip" + ) + + 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 Set>.forEach(action: (K, V) -> Unit) { forEach { action(it.key, it.value) } } -val ONGOING_SUFFIX = arrayOf( - "[ongoing]", - "(ongoing)", - "{ongoing}", - "", - "ongoing", - "[incomplete]", - "(incomplete)", - "{incomplete}", - "", - "incomplete", - "[wip]", - "(wip)", - "{wip}", - "", - "wip" -) - -val EX_DATE_FORMAT = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US) +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) + } +} diff --git a/app/src/main/java/exh/metadata/metadata/EHentaiSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/EHentaiSearchMetadata.kt index 51d53cd4c..7be313061 100644 --- a/app/src/main/java/exh/metadata/metadata/EHentaiSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/EHentaiSearchMetadata.kt @@ -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> { val pairs = mutableListOf>() - 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 } diff --git a/app/src/main/java/exh/metadata/metadata/EightMusesSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/EightMusesSearchMetadata.kt index 8e65978c8..c440259d6 100644 --- a/app/src/main/java/exh/metadata/metadata/EightMusesSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/EightMusesSearchMetadata.kt @@ -41,12 +41,12 @@ class EightMusesSearchMetadata : RaisedSearchMetadata() { override fun getExtraInfoPairs(context: Context): List> { val pairs = mutableListOf>() - 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 } diff --git a/app/src/main/java/exh/metadata/metadata/HBrowseSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/HBrowseSearchMetadata.kt index 9fdf045ee..637d09cae 100644 --- a/app/src/main/java/exh/metadata/metadata/HBrowseSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/HBrowseSearchMetadata.kt @@ -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> { val pairs = mutableListOf>() - 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" diff --git a/app/src/main/java/exh/metadata/metadata/HentaiCafeSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/HentaiCafeSearchMetadata.kt index baac866db..3cb97a152 100644 --- a/app/src/main/java/exh/metadata/metadata/HentaiCafeSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/HentaiCafeSearchMetadata.kt @@ -48,11 +48,11 @@ class HentaiCafeSearchMetadata : RaisedSearchMetadata() { override fun getExtraInfoPairs(context: Context): List> { val pairs = mutableListOf>() - 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 } diff --git a/app/src/main/java/exh/metadata/metadata/HitomiSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/HitomiSearchMetadata.kt index 5c9deb39b..4522fdd05 100644 --- a/app/src/main/java/exh/metadata/metadata/HitomiSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/HitomiSearchMetadata.kt @@ -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> { val pairs = mutableListOf>() - 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) } - val artists = artists.joinToString() - if (artists.isNotBlank()) { - pairs += Pair(context.getString(R.string.artist), artists) + 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 += getString(R.string.artist) to artists + } + 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 += getString(R.string.series) to series + } + val characters = characters.joinToString() + if (characters.isNotBlank()) { + pairs += getString(R.string.characters) to characters + } + uploadDate?.let { pairs += getString(R.string.date_posted) to MetadataUtil.EX_DATE_FORMAT.format(Date(it)) } } - 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) } - val series = series.joinToString() - if (series.isNotBlank()) { - pairs += Pair(context.getString(R.string.series), series) - } - val characters = characters.joinToString() - if (characters.isNotBlank()) { - pairs += Pair(context.getString(R.string.characters), characters) - } - uploadDate?.let { pairs += Pair(context.getString(R.string.date_posted), EX_DATE_FORMAT.format(Date(it))) } return pairs } diff --git a/app/src/main/java/exh/metadata/metadata/MangaDexSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/MangaDexSearchMetadata.kt index 981d5f426..c1d2b9236 100644 --- a/app/src/main/java/exh/metadata/metadata/MangaDexSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/MangaDexSearchMetadata.kt @@ -78,24 +78,24 @@ class MangaDexSearchMetadata : RaisedSearchMetadata() { override fun getExtraInfoPairs(context: Context): List> { val pairs = mutableListOf>() - 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 } diff --git a/app/src/main/java/exh/metadata/metadata/NHentaiSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/NHentaiSearchMetadata.kt index 5ded3f935..4103b034b 100644 --- a/app/src/main/java/exh/metadata/metadata/NHentaiSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/NHentaiSearchMetadata.kt @@ -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> { val pairs = mutableListOf>() - 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 } diff --git a/app/src/main/java/exh/metadata/metadata/PervEdenSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/PervEdenSearchMetadata.kt index 99cf5cf60..82aa27d88 100644 --- a/app/src/main/java/exh/metadata/metadata/PervEdenSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/PervEdenSearchMetadata.kt @@ -95,19 +95,19 @@ class PervEdenSearchMetadata : RaisedSearchMetadata() { override fun getExtraInfoPairs(context: Context): List> { val pairs = mutableListOf>() - 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 } diff --git a/app/src/main/java/exh/metadata/metadata/PururinSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/PururinSearchMetadata.kt index 091d86e79..5b6e42723 100644 --- a/app/src/main/java/exh/metadata/metadata/PururinSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/PururinSearchMetadata.kt @@ -64,16 +64,16 @@ class PururinSearchMetadata : RaisedSearchMetadata() { override fun getExtraInfoPairs(context: Context): List> { val pairs = mutableListOf>() - 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 } diff --git a/app/src/main/java/exh/metadata/metadata/TsuminoSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/TsuminoSearchMetadata.kt index e8bea7a17..44847dc27 100644 --- a/app/src/main/java/exh/metadata/metadata/TsuminoSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/TsuminoSearchMetadata.kt @@ -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> { val pairs = mutableListOf>() - 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 } diff --git a/app/src/main/java/exh/search/Text.kt b/app/src/main/java/exh/search/Text.kt index eccf75547..691aeba88 100755 --- a/app/src/main/java/exh/search/Text.kt +++ b/app/src/main/java/exh/search/Text.kt @@ -1,7 +1,6 @@ package exh.search import exh.plusAssign -import exh.search.SearchEngine.Companion.escapeLike class Text : QueryComponent() { val components = mutableListOf() @@ -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()) } diff --git a/app/src/main/java/exh/source/EnhancedHttpSource.kt b/app/src/main/java/exh/source/EnhancedHttpSource.kt index 3213297ac..d252d6e14 100644 --- a/app/src/main/java/exh/source/EnhancedHttpSource.kt +++ b/app/src/main/java/exh/source/EnhancedHttpSource.kt @@ -235,21 +235,22 @@ class EnhancedHttpSource( originalSource } } - - companion object { - fun Source.getMainSource(): Source { - return if (this is EnhancedHttpSource) { - this.source() - } else { - this - } - } - fun Source.getOriginalSource(): Source { - return if (this is EnhancedHttpSource) { - this.originalSource - } else { - this - } - } - } +} + +fun Source.getMainSource(): Source = if (this is EnhancedHttpSource) { + this.source() +} else { + this +} + +fun Source.getOriginalSource(): Source = if (this is EnhancedHttpSource) { + this.originalSource +} else { + this +} + +fun Source.getEnhancedSource(): Source = if (this is EnhancedHttpSource) { + this.enhancedSource +} else { + this } diff --git a/app/src/main/java/exh/ui/captcha/AutoSolvingWebViewClient.kt b/app/src/main/java/exh/ui/captcha/AutoSolvingWebViewClient.kt index 895d4b01f..151478d9e 100644 --- a/app/src/main/java/exh/ui/captcha/AutoSolvingWebViewClient.kt +++ b/app/src/main/java/exh/ui/captcha/AutoSolvingWebViewClient.kt @@ -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", diff --git a/app/src/main/java/exh/ui/metadata/MetadataViewController.kt b/app/src/main/java/exh/ui/metadata/MetadataViewController.kt index 6b243f2b5..b14706080 100644 --- a/app/src/main/java/exh/ui/metadata/MetadataViewController.kt +++ b/app/src/main/java/exh/ui/metadata/MetadataViewController.kt @@ -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 diff --git a/app/src/main/java/exh/ui/metadata/adapters/EHentaiDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/EHentaiDescriptionAdapter.kt index 48af82a7f..f3c0623a7 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/EHentaiDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/EHentaiDescriptionAdapter.kt @@ -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, diff --git a/app/src/main/java/exh/ui/metadata/adapters/EightMusesDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/EightMusesDescriptionAdapter.kt index 72dde8c6e..649bbd7b7 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/EightMusesDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/EightMusesDescriptionAdapter.kt @@ -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 { diff --git a/app/src/main/java/exh/ui/metadata/adapters/HBrowseDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/HBrowseDescriptionAdapter.kt index 565710c48..08a832f43 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/HBrowseDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/HBrowseDescriptionAdapter.kt @@ -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 { diff --git a/app/src/main/java/exh/ui/metadata/adapters/HentaiCafeDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/HentaiCafeDescriptionAdapter.kt index fa23e6dff..f27578600 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/HentaiCafeDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/HentaiCafeDescriptionAdapter.kt @@ -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 { diff --git a/app/src/main/java/exh/ui/metadata/adapters/HitomiDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/HitomiDescriptionAdapter.kt index e5516ca81..8b0c92ad0 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/HitomiDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/HitomiDescriptionAdapter.kt @@ -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, diff --git a/app/src/main/java/exh/ui/metadata/adapters/MangaDexDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/MangaDexDescriptionAdapter.kt index ca418c1a2..4bf0b955c 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/MangaDexDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/MangaDexDescriptionAdapter.kt @@ -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 { diff --git a/app/src/main/java/exh/ui/metadata/adapters/NHentaiDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/NHentaiDescriptionAdapter.kt index d21f30f37..d6a933064 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/NHentaiDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/NHentaiDescriptionAdapter.kt @@ -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, diff --git a/app/src/main/java/exh/ui/metadata/adapters/PervEdenDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/PervEdenDescriptionAdapter.kt index afc73cf8d..4f32d005a 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/PervEdenDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/PervEdenDescriptionAdapter.kt @@ -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, diff --git a/app/src/main/java/exh/ui/metadata/adapters/PururinDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/PururinDescriptionAdapter.kt index b2f3ba379..c9f647dee 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/PururinDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/PururinDescriptionAdapter.kt @@ -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) - } - - 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.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) + } 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, diff --git a/app/src/main/java/exh/ui/metadata/adapters/TsuminoDescriptionAdapter.kt b/app/src/main/java/exh/ui/metadata/adapters/TsuminoDescriptionAdapter.kt index 30d75c353..6b299f1a8 100644 --- a/app/src/main/java/exh/ui/metadata/adapters/TsuminoDescriptionAdapter.kt +++ b/app/src/main/java/exh/ui/metadata/adapters/TsuminoDescriptionAdapter.kt @@ -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, diff --git a/app/src/main/java/exh/util/CachedField.kt b/app/src/main/java/exh/util/CachedField.kt deleted file mode 100644 index 8e58e4e41..000000000 --- a/app/src/main/java/exh/util/CachedField.kt +++ /dev/null @@ -1,24 +0,0 @@ -package exh.util - -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock - -class CachedField(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!! - } - } -} diff --git a/app/src/main/java/exh/util/JsonReaderObjectReader.kt b/app/src/main/java/exh/util/JsonReaderObjectReader.kt deleted file mode 100644 index c730f1049..000000000 --- a/app/src/main/java/exh/util/JsonReaderObjectReader.kt +++ /dev/null @@ -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 -} diff --git a/app/src/main/java/exh/util/Math.kt b/app/src/main/java/exh/util/Math.kt index b142a4578..3c2a0be3d 100644 --- a/app/src/main/java/exh/util/Math.kt +++ b/app/src/main/java/exh/util/Math.kt @@ -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 diff --git a/app/src/main/java/exh/util/NakedTrie.kt b/app/src/main/java/exh/util/NakedTrie.kt deleted file mode 100644 index 8313da6e6..000000000 --- a/app/src/main/java/exh/util/NakedTrie.kt +++ /dev/null @@ -1,368 +0,0 @@ -package exh.util - -import android.util.SparseArray -import java.util.AbstractMap -import java.util.LinkedList - -class NakedTrieNode(val key: Int, var parent: NakedTrieNode?) { - val children = SparseArray>(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>>() - 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? { - 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 : MutableMap { - /** - * 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(-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? { - 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>() - 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) { - // 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 { - val node = getAsNode(prefix) ?: return emptyMap() - - return object : Map { - /** - * Returns a read-only [Set] of all key/value pairs in this map. - */ - override val entries: Set> - get() { - val out = mutableSetOf>() - 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 - get() { - val out = mutableSetOf() - 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 - get() { - val out = mutableSetOf() - 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> - get() = FakeMutableSet.fromSet( - mutableSetOf>().apply { - walk { k, v -> - this += FakeMutableEntry.fromPair(k, v) - true - } - } - ) - - /** - * Returns a [MutableSet] of all keys in this map. - */ - override val keys: MutableSet - get() = FakeMutableSet.fromSet( - mutableSetOf().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 - get() = FakeMutableCollection.fromCollection( - mutableListOf().apply { - walk { _, v -> - this += v - true - } - } - ) -} diff --git a/app/src/main/java/exh/util/SearchOverride.kt b/app/src/main/java/exh/util/SearchOverride.kt index ab0f16d53..98c87055c 100644 --- a/app/src/main/java/exh/util/SearchOverride.kt +++ b/app/src/main/java/exh/util/SearchOverride.kt @@ -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) = +fun UrlImportableSource.urlImportFetchSearchManga(context: Context, query: String, fail: () -> Observable): Observable = when { query.startsWith("http://") || query.startsWith("https://") -> { Observable.fromCallable { diff --git a/app/src/main/java/exh/util/SourceTagsUtil.kt b/app/src/main/java/exh/util/SourceTagsUtil.kt index 8b941abc3..327bbc3f6 100644 --- a/app/src/main/java/exh/util/SourceTagsUtil.kt +++ b/app/src/main/java/exh/util/SourceTagsUtil.kt @@ -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,52 +47,53 @@ class SourceTagsUtil { } else { "$namespace:$tag" } - companion object { - fun Manga.getRaisedTags(genres: List? = null): List? = (genres ?: this.getGenres())?.map { parseTag(it) } - fun parseTag(tag: String) = RaisedTag( - ( - if (tag.startsWith("-")) { - tag.substringAfter("-") - } else { - tag - } - ).substringBefore(':', missingDelimiterValue = "").trimOrNull(), - tag.substringAfter(':', missingDelimiterValue = tag).trim(), - if (tag.startsWith("-")) TAG_TYPE_EXCLUDE else TAG_TYPE_DEFAULT - ) + fun parseTag(tag: String) = RaisedTag( + ( + if (tag.startsWith("-")) { + tag.substringAfter("-") + } else { + tag + } + ).substringBefore(':', missingDelimiterValue = "").trimOrNull(), + tag.substringAfter(':', missingDelimiterValue = tag).trim(), + if (tag.startsWith("-")) TAG_TYPE_EXCLUDE else TAG_TYPE_DEFAULT + ) - const val TAG_TYPE_EXCLUDE = 69 // why not + const val TAG_TYPE_EXCLUDE = 69 // why not - const val DOUJINSHI_COLOR = "#f44336" - const val MANGA_COLOR = "#ff9800" - const val ARTIST_CG_COLOR = "#fbc02d" - const val GAME_CG_COLOR = "#4caf50" - const val WESTERN_COLOR = "#8bc34a" - const val NON_H_COLOR = "#2196f3" - const val IMAGE_SET_COLOR = "#3f51b5" - const val COSPLAY_COLOR = "#9c27b0" - const val ASIAN_PORN_COLOR = "#9575cd" - const val MISC_COLOR = "#f06292" + const val DOUJINSHI_COLOR = "#f44336" + const val MANGA_COLOR = "#ff9800" + const val ARTIST_CG_COLOR = "#fbc02d" + const val GAME_CG_COLOR = "#4caf50" + const val WESTERN_COLOR = "#8bc34a" + const val NON_H_COLOR = "#2196f3" + const val IMAGE_SET_COLOR = "#3f51b5" + const val COSPLAY_COLOR = "#9c27b0" + const val ASIAN_PORN_COLOR = "#9575cd" + const val MISC_COLOR = "#f06292" - fun getLocaleSourceUtil(language: String?) = when (language) { - "english", "eng" -> Locale("en") - "chinese" -> Locale("zh") - "spanish" -> Locale("es") - "korean" -> Locale("ko") - "russian" -> Locale("ru") - "french" -> Locale("fr") - "portuguese" -> Locale("pt") - "thai" -> Locale("th") - "german" -> Locale("de") - "italian" -> Locale("it") - "vietnamese" -> Locale("vi") - "polish" -> Locale("pl") - "hungarian" -> Locale("hu") - "dutch" -> Locale("nl") - else -> null - } - - private const val TAG_TYPE_DEFAULT = 1 + fun getLocaleSourceUtil(language: String?) = when (language) { + "english", "eng" -> Locale("en") + "chinese" -> Locale("zh") + "spanish" -> Locale("es") + "korean" -> Locale("ko") + "russian" -> Locale("ru") + "french" -> Locale("fr") + "portuguese" -> Locale("pt") + "thai" -> Locale("th") + "german" -> Locale("de") + "italian" -> Locale("it") + "vietnamese" -> Locale("vi") + "polish" -> Locale("pl") + "hungarian" -> Locale("hu") + "dutch" -> Locale("nl") + else -> null } + + private const val TAG_TYPE_DEFAULT = 1 +} + +fun Manga.getRaisedTags(genres: List? = null): List? = (genres ?: this.getGenres())?.map { + SourceTagsUtil.parseTag(it) } diff --git a/app/src/main/java/exh/util/SparseArrayCollection.kt b/app/src/main/java/exh/util/SparseArrayCollection.kt deleted file mode 100644 index 10259fd29..000000000 --- a/app/src/main/java/exh/util/SparseArrayCollection.kt +++ /dev/null @@ -1,73 +0,0 @@ -package exh.util - -import android.util.SparseArray -import java.util.AbstractMap - -class SparseArrayKeyCollection(val sparseArray: SparseArray, var reverse: Boolean = false) : AbstractCollection() { - override val size get() = sparseArray.size() - - override fun iterator() = object : Iterator { - 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(val sparseArray: SparseArray, var reverse: Boolean = false) : AbstractCollection() { - override val size get() = sparseArray.size() - - override fun iterator() = object : Iterator { - 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(val sparseArray: SparseArray, var reverse: Boolean = false) : AbstractCollection>() { - override val size get() = sparseArray.size() - - override fun iterator() = object : Iterator> { - 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 { - var idx = index++ - if (reverse) idx = sparseArray.size() - 1 - idx - return AbstractMap.SimpleImmutableEntry( - sparseArray.keyAt(idx), - sparseArray.valueAt(idx) - ) - } - } -} diff --git a/app/src/main/java/exh/util/ViewExtensions.kt b/app/src/main/java/exh/util/ViewExtensions.kt index 5d86215cb..4b446e512 100644 --- a/app/src/main/java/exh/util/ViewExtensions.kt +++ b/app/src/main/java/exh/util/ViewExtensions.kt @@ -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?, 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 } } diff --git a/app/src/main/java/exh/util/ViewUtil.kt b/app/src/main/java/exh/util/ViewUtil.kt deleted file mode 100644 index 4d4e98bc1..000000000 --- a/app/src/main/java/exh/util/ViewUtil.kt +++ /dev/null @@ -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() -} diff --git a/app/src/main/java/exh/widget/preference/MangadexLoginDialog.kt b/app/src/main/java/exh/widget/preference/MangadexLoginDialog.kt index 95f677c7c..74438cd51 100644 --- a/app/src/main/java/exh/widget/preference/MangadexLoginDialog.kt +++ b/app/src/main/java/exh/widget/preference/MangadexLoginDialog.kt @@ -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().get(args.getLong("key", 0))?.getMainSource() as? MangaDex val service = Injekt.get().mdList diff --git a/app/src/main/java/exh/widget/preference/MangadexLogoutDialog.kt b/app/src/main/java/exh/widget/preference/MangadexLogoutDialog.kt index 0fdcefc71..34755af7d 100644 --- a/app/src/main/java/exh/widget/preference/MangadexLogoutDialog.kt +++ b/app/src/main/java/exh/widget/preference/MangadexLogoutDialog.kt @@ -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().get(args.getLong("key", 0))?.getMainSource() as? MangaDex val trackManager: TrackManager by injectLazy() diff --git a/app/src/main/java/org/vepta/vdm/ByteCursor.kt b/app/src/main/java/org/vepta/vdm/ByteCursor.kt deleted file mode 100644 index bbcbf2b0e..000000000 --- a/app/src/main/java/org/vepta/vdm/ByteCursor.kt +++ /dev/null @@ -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 -} diff --git a/app/src/main/java/xyz/nulldev/ts/api/http/serializer/FilterSerializer.kt b/app/src/main/java/xyz/nulldev/ts/api/http/serializer/FilterSerializer.kt index 52345fc89..45cf56323 100644 --- a/app/src/main/java/xyz/nulldev/ts/api/http/serializer/FilterSerializer.kt +++ b/app/src/main/java/xyz/nulldev/ts/api/http/serializer/FilterSerializer.kt @@ -34,20 +34,18 @@ class FilterSerializer { ) fun serialize(filters: FilterList) = buildJsonArray { - filters.forEach { - @Suppress("UNCHECKED_CAST") - add(serialize(it as Filter)) + filters.filterIsInstance>().forEach { + add(serialize(it)) } } fun serialize(filter: Filter): 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> - - return buildJsonObject { + return serializers + .filterIsInstance>>() + .firstOrNull { + filter::class.isSubclassOf(it.clazz) + }?.let { serializer -> + buildJsonObject { with(serializer) { serialize(filter) } val classMappings = mutableListOf>() @@ -66,26 +64,21 @@ 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, obj.jsonObject) + filters.filterIsInstance>().zip(json).forEach { (filter, obj) -> + deserialize(filter, obj.jsonObject) } } fun deserialize(filter: Filter, json: JsonObject) { - val serializer = serializers.find { - 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> + val serializer = serializers + .filterIsInstance>>() + .firstOrNull { + it.type == json[TYPE]!!.jsonPrimitive.content + } ?: throw IllegalArgumentException("Cannot deserialize this type!") serializer.deserialize(json, filter)