From 23ac3d18e5601e46689189e59bf431ab99fbfa0d Mon Sep 17 00:00:00 2001 From: jobobby04 Date: Sat, 4 Apr 2020 16:30:05 -0400 Subject: [PATCH] Optimize imports, disallow wildcard imports because of klint, run linter --- .../database/mappers/CategoryTypeMapping.kt | 1 - .../database/resolvers/MangaUrlPutResolver.kt | 2 - .../data/database/tables/CategoryTable.kt | 1 - .../data/library/LibraryUpdateNotifier.kt | 2 +- .../preference/EmptyPreferenceDataStore.kt | 2 +- .../myanimelist/MyAnimeListInterceptor.kt | 2 +- .../tachiyomi/data/updater/UpdaterNotifier.kt | 2 +- .../tachiyomi/source/ConfigurableSource.kt | 2 +- .../tachiyomi/source/online/LewdSource.kt | 2 +- .../source/online/UrlImportableSource.kt | 2 +- .../tachiyomi/source/online/all/EHentai.kt | 80 ++++++----- .../tachiyomi/source/online/all/Hitomi.kt | 20 +-- .../tachiyomi/source/online/all/NHentai.kt | 22 ++- .../tachiyomi/source/online/all/PervEden.kt | 16 ++- .../source/online/english/EightMuses.kt | 15 ++- .../source/online/english/HBrowse.kt | 12 +- .../source/online/english/HentaiCafe.kt | 2 +- .../source/online/english/Pururin.kt | 4 +- .../source/online/english/Tsumino.kt | 12 +- .../ui/base/controller/TabbedController.kt | 2 +- .../ui/base/holder/BaseViewHolder.kt | 2 +- .../ui/browse/source/filter/CheckboxItem.kt | 2 +- .../ui/browse/source/filter/SelectItem.kt | 2 +- .../ui/browse/source/filter/SortGroup.kt | 1 - .../ui/library/LibraryCategoryAdapter.kt | 13 +- .../tachiyomi/ui/library/LibraryHolder.kt | 4 +- .../ui/manga/info/MangaInfoPresenter.kt | 1 - .../tachiyomi/ui/recent/DateSectionItem.kt | 2 +- .../ui/setting/SettingsEhController.kt | 24 +++- .../kanade/tachiyomi/util/JsoupExtensions.kt | 2 +- .../util/view/ImageViewExtensions.kt | 2 +- .../util/view/ViewGroupExtensions.kt | 2 +- .../widget/preference/IntListPreference.kt | 2 +- app/src/main/java/exh/EHSourceHelpers.kt | 4 +- app/src/main/java/exh/EXHSavedSearch.kt | 8 +- app/src/main/java/exh/GalleryAdder.kt | 52 ++++---- app/src/main/java/exh/debug/DebugFunctions.kt | 11 +- app/src/main/java/exh/debug/DebugToggles.kt | 2 +- .../java/exh/debug/SettingsDebugController.kt | 16 ++- .../java/exh/eh/EHentaiThrottleManager.kt | 14 +- .../main/java/exh/eh/EHentaiUpdateHelper.kt | 16 +-- .../main/java/exh/eh/EHentaiUpdateWorker.kt | 41 +++--- .../main/java/exh/eh/EHentaiUpdaterStats.kt | 8 +- .../java/exh/eh/GalleryNotUpdatedException.kt | 2 +- .../java/exh/eh/MemAutoFlushingLookupTable.kt | 45 ++++--- .../main/java/exh/favorites/FavoriteEntry.kt | 2 +- .../java/exh/favorites/FavoritesSyncHelper.kt | 115 ++++++++-------- .../exh/favorites/LocalFavoritesStorage.kt | 42 +++--- app/src/main/java/exh/hitomi/HitomiNozomi.kt | 73 +++++----- .../main/java/exh/log/CrashlyticsPrinter.kt | 10 +- .../main/java/exh/log/EHDebugModeOverlay.kt | 8 +- app/src/main/java/exh/log/EHLogLevel.kt | 2 +- app/src/main/java/exh/log/EHNetworkLogging.kt | 2 +- .../main/java/exh/metadata/MetadataUtil.kt | 7 +- .../metadata/EHentaiSearchMetadata.kt | 44 +++--- .../metadata/EightMusesSearchMetadata.kt | 3 +- .../metadata/HBrowseSearchMetadata.kt | 4 +- .../metadata/HentaiCafeSearchMetadata.kt | 8 +- .../metadata/metadata/HitomiSearchMetadata.kt | 18 +-- .../metadata/NHentaiSearchMetadata.kt | 30 +++-- .../metadata/PervEdenSearchMetadata.kt | 17 ++- .../metadata/PururinSearchMetadata.kt | 4 +- .../metadata/TsuminoSearchMetadata.kt | 12 +- .../metadata/metadata/base/FlatMetadata.kt | 16 +-- .../metadata/base/RaisedSearchMetadata.kt | 26 ++-- .../exh/metadata/metadata/base/RaisedTag.kt | 8 +- .../exh/metadata/metadata/base/RaisedTitle.kt | 6 +- .../exh/metadata/sql/models/SearchMetadata.kt | 12 +- .../java/exh/metadata/sql/models/SearchTag.kt | 12 +- .../exh/metadata/sql/models/SearchTitle.kt | 8 +- .../sql/queries/SearchMetadataQueries.kt | 3 +- .../metadata/sql/queries/SearchTagQueries.kt | 2 +- .../sql/queries/SearchTitleQueries.kt | 4 +- .../exh/patch/UniversalCaptchaDetection.kt | 4 +- app/src/main/java/exh/search/Namespace.kt | 6 +- .../main/java/exh/search/QueryComponent.kt | 2 +- app/src/main/java/exh/search/SearchEngine.kt | 56 ++++---- app/src/main/java/exh/search/Text.kt | 20 +-- .../java/exh/smartsearch/SmartSearchEngine.kt | 34 +++-- .../java/exh/source/DelegatedHttpSource.kt | 55 ++++---- .../java/exh/source/EnhancedHttpSource.kt | 64 +++++---- .../uconfig/ConfiguringDialogController.kt | 5 +- .../main/java/exh/uconfig/EHConfigurator.kt | 52 ++++---- .../java/exh/uconfig/EHHathPerksResponse.kt | 5 +- .../main/java/exh/uconfig/EhUConfigBuilder.kt | 36 ++--- .../uconfig/WarnConfigureDialogController.kt | 4 +- app/src/main/java/exh/ui/LoaderManager.kt | 14 +- .../java/exh/ui/base/BaseExhController.kt | 2 +- .../exh/ui/batchadd/BatchAddController.kt | 13 +- .../java/exh/ui/batchadd/BatchAddPresenter.kt | 6 +- .../ui/captcha/AutoSolvingWebViewClient.kt | 18 +-- .../java/exh/ui/captcha/BasicWebViewClient.kt | 14 +- .../exh/ui/captcha/BrowserActionActivity.kt | 126 ++++++++++-------- .../captcha/HeadersInjectingWebViewClient.kt | 12 +- .../main/java/exh/ui/captcha/WebViewUtil.kt | 2 +- .../exh/ui/intercept/InterceptActivity.kt | 6 +- .../intercept/InterceptActivityPresenter.kt | 14 +- .../java/exh/ui/lock/FingerLockPreference.kt | 20 +-- .../java/exh/ui/lock/LockActivityDelegate.kt | 4 - .../java/exh/ui/lock/LockChangeHandler.kt | 6 +- .../main/java/exh/ui/lock/LockController.kt | 14 +- .../main/java/exh/ui/lock/LockPreference.kt | 10 +- .../main/java/exh/ui/lock/LockPresenter.kt | 11 +- app/src/main/java/exh/ui/lock/LockUtils.kt | 27 ++-- .../main/java/exh/ui/login/LoginController.kt | 30 ++--- .../main/java/exh/ui/login/LoginPresenter.kt | 4 +- .../exh/ui/migration/MetadataFetchDialog.kt | 21 ++- .../java/exh/ui/migration/MigrationStatus.kt | 2 +- .../manga/design/MigrationDesignController.kt | 18 +-- .../manga/design/MigrationSourceAdapter.kt | 8 +- .../manga/design/MigrationSourceHolder.kt | 10 +- .../manga/design/MigrationSourceItem.kt | 16 ++- .../manga/process/DeactivatableViewPager.kt | 6 +- .../migration/manga/process/MigratingManga.kt | 19 +-- .../process/MigrationProcedureAdapter.kt | 47 ++++--- .../manga/process/MigrationProcedureConfig.kt | 16 +-- .../process/MigrationProcedureController.kt | 94 +++++++------ .../ui/smartsearch/SmartSearchController.kt | 14 +- .../ui/smartsearch/SmartSearchPresenter.kt | 20 +-- app/src/main/java/exh/util/CachedField.kt | 2 +- app/src/main/java/exh/util/CoroutineUtil.kt | 4 +- app/src/main/java/exh/util/DeferredField.kt | 4 +- app/src/main/java/exh/util/ExceptionUtil.kt | 4 +- app/src/main/java/exh/util/FakeMutables.kt | 5 +- .../java/exh/util/JsonReaderObjectReader.kt | 8 +- .../main/java/exh/util/LoggingRealmQuery.kt | 19 ++- app/src/main/java/exh/util/NakedTrie.kt | 59 ++++---- app/src/main/java/exh/util/OkHttpUtil.kt | 6 +- app/src/main/java/exh/util/RealmUtil.kt | 15 +-- app/src/main/java/exh/util/RxUtil.kt | 10 +- app/src/main/java/exh/util/SearchOverride.kt | 2 +- .../java/exh/util/SparseArrayCollection.kt | 12 +- app/src/main/java/exh/util/UriFilter.kt | 2 +- app/src/main/java/exh/util/UriGroup.kt | 4 +- app/src/main/java/exh/util/ViewUtil.kt | 2 +- app/src/main/java/org/vepta/vdm/ByteCursor.kt | 58 ++++---- .../api/http/serializer/FilterSerializer.kt | 25 +++- .../http/serializer/FilterSerializerModels.kt | 12 +- 138 files changed, 1192 insertions(+), 1027 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/CategoryTypeMapping.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/CategoryTypeMapping.kt index 11c467c9d..0434a8376 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/CategoryTypeMapping.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/CategoryTypeMapping.kt @@ -43,7 +43,6 @@ class CategoryPutResolver : DefaultPutResolver() { put(COL_FLAGS, obj.flags) val orderString = obj.mangaOrder.joinToString("/") put(COL_MANGA_ORDER, orderString) - } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaUrlPutResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaUrlPutResolver.kt index ca4d7fc0e..5feac16c1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaUrlPutResolver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaUrlPutResolver.kt @@ -29,6 +29,4 @@ class MangaUrlPutResolver : PutResolver() { fun mapToContentValues(manga: Manga) = ContentValues(1).apply { put(MangaTable.COL_URL, manga.url) } - } - diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/CategoryTable.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/CategoryTable.kt index 17a6e75c4..d3b9477b8 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/CategoryTable.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/CategoryTable.kt @@ -24,7 +24,6 @@ object CategoryTable { $COL_MANGA_ORDER TEXT NOT NULL )""" - val addMangaOrder: String get() = "ALTER TABLE $TABLE ADD COLUMN $COL_MANGA_ORDER TEXT" } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt index 4bda1dfa1..57b7195e6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt @@ -72,4 +72,4 @@ class LibraryUpdateNotifier(private val context: Context) { intent.action = MainActivity.SHORTCUT_RECENTLY_UPDATED return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) } -} \ No newline at end of file +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/EmptyPreferenceDataStore.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/EmptyPreferenceDataStore.kt index d162cfd65..2f2081a27 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/EmptyPreferenceDataStore.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/EmptyPreferenceDataStore.kt @@ -45,4 +45,4 @@ class EmptyPreferenceDataStore : PreferenceDataStore() { override fun putStringSet(key: String?, values: Set?) { } -} \ No newline at end of file +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListInterceptor.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListInterceptor.kt index 09873f84b..a39f8f6ed 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListInterceptor.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListInterceptor.kt @@ -57,4 +57,4 @@ class MyAnimeListInterceptor(private val myanimelist: MyAnimeList) : Interceptor return newBody.toString().toRequestBody(requestBody.contentType()) } -} \ No newline at end of file +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterNotifier.kt index cbab3f73b..440b40067 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterNotifier.kt @@ -110,4 +110,4 @@ internal class UpdaterNotifier(private val context: Context) { } notificationBuilder.show(Notifications.ID_UPDATER) } -} \ No newline at end of file +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/ConfigurableSource.kt b/app/src/main/java/eu/kanade/tachiyomi/source/ConfigurableSource.kt index ed82ff6f8..4f5154fe5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/ConfigurableSource.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/ConfigurableSource.kt @@ -5,4 +5,4 @@ import androidx.preference.PreferenceScreen interface ConfigurableSource : Source { fun setupPreferenceScreen(screen: PreferenceScreen) -} \ No newline at end of file +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/LewdSource.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/LewdSource.kt index e27951e78..8b2384219 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/LewdSource.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/LewdSource.kt @@ -9,11 +9,11 @@ import eu.kanade.tachiyomi.source.model.SManga import exh.metadata.metadata.base.RaisedSearchMetadata import exh.metadata.metadata.base.getFlatMetadataForManga import exh.metadata.metadata.base.insertFlatMetadata +import kotlin.reflect.KClass import rx.Completable import rx.Single import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get -import kotlin.reflect.KClass /** * LEWD! diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/UrlImportableSource.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/UrlImportableSource.kt index fce3cb19c..a9357d956 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/UrlImportableSource.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/UrlImportableSource.kt @@ -28,4 +28,4 @@ interface UrlImportableSource : Source { url } } -} \ No newline at end of file +} 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 80d187921..e349566c6 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 @@ -3,7 +3,12 @@ package eu.kanade.tachiyomi.source.online.all import android.content.Context import android.net.Uri import com.elvishew.xlog.XLog -import com.github.salomonbrys.kotson.* +import com.github.salomonbrys.kotson.array +import com.github.salomonbrys.kotson.get +import com.github.salomonbrys.kotson.int +import com.github.salomonbrys.kotson.obj +import com.github.salomonbrys.kotson.set +import com.github.salomonbrys.kotson.string import com.google.gson.JsonArray import com.google.gson.JsonObject import com.google.gson.JsonParser @@ -13,7 +18,12 @@ import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.network.asObservableWithAsyncStacktrace -import eu.kanade.tachiyomi.source.model.* +import eu.kanade.tachiyomi.source.model.Filter +import eu.kanade.tachiyomi.source.model.FilterList +import eu.kanade.tachiyomi.source.model.MangasPage +import eu.kanade.tachiyomi.source.model.Page +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.LewdSource import eu.kanade.tachiyomi.source.online.UrlImportableSource @@ -36,23 +46,30 @@ import exh.util.UriFilter import exh.util.UriGroup import exh.util.ignore import exh.util.urlImportFetchSearchManga +import java.net.URLEncoder +import java.util.ArrayList import kotlinx.coroutines.runBlocking -import okhttp3.* +import okhttp3.CacheControl +import okhttp3.CookieJar +import okhttp3.Headers import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.Request +import okhttp3.RequestBody +import okhttp3.Response import org.jsoup.nodes.Document import org.jsoup.nodes.Element import org.jsoup.nodes.TextNode import rx.Observable import rx.Single import uy.kohesive.injekt.injectLazy -import java.net.URLEncoder -import java.util.* // TODO Consider gallery updating when doing tabbed browsing -class EHentai(override val id: Long, - val exh: Boolean, - val context: Context) : HttpSource(), LewdSource, UrlImportableSource { +class EHentai( + override val id: Long, + val exh: Boolean, + val context: Context +) : HttpSource(), LewdSource, UrlImportableSource { override val metaClass = EHentaiSearchMetadata::class val schema: String @@ -98,10 +115,10 @@ class EHentai(override val id: Long, favElement?.attr("style")?.substring(14, 17) ), manga = Manga.create(id).apply { - //Get title + // Get title title = thumbnailElement.attr("title") url = EHentaiSearchMetadata.normalizeUrl(linkElement.attr("href")) - //Get image + // Get image thumbnail_url = thumbnailElement.attr("src") // TODO Parse genre + uploader + tags @@ -110,9 +127,9 @@ class EHentai(override val id: Long, val parsedLocation = doc.location().toHttpUrlOrNull() - //Add to page if required - val hasNextPage = if (parsedLocation == null - || !parsedLocation.queryParameterNames.contains(REVERSE_PARAM)) { + // Add to page if required + val hasNextPage = if (parsedLocation == null || + !parsedLocation.queryParameterNames.contains(REVERSE_PARAM)) { select("a[onclick=return false]").last()?.let { it.text() == ">" } ?: false @@ -212,8 +229,11 @@ class EHentai(override val id: Long, } }!! - private fun fetchChapterPage(chapter: SChapter, np: String, - pastUrls: List = emptyList()): Observable> { + private fun fetchChapterPage( + chapter: SChapter, + np: String, + pastUrls: List = emptyList() + ): Observable> { val urls = ArrayList(pastUrls) return chapterPageCall(np).flatMap { val jsoup = it.asJsoup() @@ -245,7 +265,7 @@ class EHentai(override val id: Long, else exGet("$baseUrl/toplist.php?tl=15&p=${page - 1}", null) // Custom page logic for toplists - //Support direct URL importing + // Support direct URL importing override fun fetchSearchManga(page: Int, query: String, filters: FilterList) = urlImportFetchSearchManga(query) { searchMangaRequestObservable(page, query, filters).flatMap { @@ -377,7 +397,7 @@ class EHentai(override val id: Long, uploader = select("#gdn").text().nullIfBlank()?.trim() - //Parse the table + // Parse the table select("#gdd tr").forEach { val left = it.select(".gdt1").text().nullIfBlank()?.trim() val rightElement = it.selectFirst(".gdt2") @@ -407,13 +427,13 @@ class EHentai(override val id: Long, } lastUpdateCheck = System.currentTimeMillis() - if (datePosted != null - && lastUpdateCheck - datePosted!! > EHentaiUpdateWorkerConstants.GALLERY_AGE_TIME) { + if (datePosted != null && + lastUpdateCheck - datePosted!! > EHentaiUpdateWorkerConstants.GALLERY_AGE_TIME) { aged = true XLog.d("aged %s - too old", title) } - //Parse ratings + // Parse ratings ignore { averageRating = select("#rating_label") .text() @@ -428,7 +448,7 @@ class EHentai(override val id: Long, ?.toInt() } - //Parse tags + // Parse tags tags.clear() select("#taglist tr").forEach { val namespace = it.select(".tc").text().removeSuffix(":") @@ -465,7 +485,7 @@ class EHentai(override val id: Long, fun realImageUrlParse(response: Response, page: Page): String { with(response.asJsoup()) { val currentImage = getElementById("img").attr("src") - //Each press of the retry button will choose another server + // Each press of the retry button will choose another server select("#loadfail").attr("onclick").nullIfBlank()?.let { page.url = addParam(page.url, "nl", it.substring(it.indexOf('\'') + 1 until it.lastIndexOf('\''))) } @@ -490,17 +510,17 @@ class EHentai(override val id: Long, cache = false)).execute() val doc = response2.asJsoup() - //Parse favorites + // Parse favorites val parsed = extendedGenericMangaParse(doc) result += parsed.first - //Parse fav names + // Parse fav names if (favNames == null) favNames = doc.select(".fp:not(.fps)").mapNotNull { it.child(2).text() } - //Next page + // Next page page++ } while (parsed.second) @@ -544,7 +564,7 @@ class EHentai(override val id: Long, fun cookiesHeader(sp: Int = spPref().getOrDefault()) = buildCookies(rawCookies(sp)) - //Headers + // Headers override fun headersBuilder() = super.headersBuilder().add("Cookie", cookiesHeader())!! fun addParam(url: String, param: String, value: String) = Uri.parse(url) @@ -565,7 +585,7 @@ class EHentai(override val id: Long, chain.proceed(newReq) }.build()!! - //Filters + // Filters override fun getFilterList() = FilterList( Watched(), GenreGroup(), @@ -673,11 +693,11 @@ class EHentai(override val id: Long, override fun mapUrlToMangaUrl(uri: Uri): String? { return when (uri.pathSegments.firstOrNull()) { "g" -> { - //Is already gallery page, do nothing + // Is already gallery page, do nothing uri.toString() } "s" -> { - //Is page, fetch gallery token and use that + // Is page, fetch gallery token and use that getGalleryUrlFromPage(uri) } else -> null @@ -713,7 +733,6 @@ class EHentai(override val id: Long, return "${uri.scheme}://${uri.host}/g/${obj["gid"].int}/${obj["token"].string}/" } - companion object { private const val QUERY_PREFIX = "?f_apply=Apply+Filter" private const val TR_SUFFIX = "TR" @@ -738,6 +757,5 @@ class EHentai(override val id: Long, fun buildCookies(cookies: Map) = cookies.entries.joinToString(separator = "; ") { "${URLEncoder.encode(it.key, "UTF-8")}=${URLEncoder.encode(it.value, "UTF-8")}" } - } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/Hitomi.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/Hitomi.kt index 58ed0dbf7..ceeb97df0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/Hitomi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/Hitomi.kt @@ -10,7 +10,11 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.asObservableSuccess -import eu.kanade.tachiyomi.source.model.* +import eu.kanade.tachiyomi.source.model.FilterList +import eu.kanade.tachiyomi.source.model.MangasPage +import eu.kanade.tachiyomi.source.model.Page +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.LewdSource import eu.kanade.tachiyomi.source.online.UrlImportableSource @@ -24,6 +28,8 @@ import exh.metadata.metadata.HitomiSearchMetadata.Companion.TAG_TYPE_DEFAULT import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.TAG_TYPE_VIRTUAL import exh.metadata.metadata.base.RaisedTag import exh.util.urlImportFetchSearchManga +import java.text.SimpleDateFormat +import java.util.Locale import okhttp3.Request import okhttp3.Response import org.jsoup.nodes.Document @@ -32,8 +38,6 @@ import rx.Observable import rx.Single import rx.schedulers.Schedulers import uy.kohesive.injekt.injectLazy -import java.text.SimpleDateFormat -import java.util.* /** * Man, I hate this source :( @@ -61,8 +65,8 @@ class Hitomi : HttpSource(), LewdSource, UrlImpo private var tagIndexVersionCacheTime: Long = 0 private fun tagIndexVersion(): Single { val sCachedTagIndexVersion = cachedTagIndexVersion - return if (sCachedTagIndexVersion == null - || tagIndexVersionCacheTime + INDEX_VERSION_CACHE_TIME_MS < System.currentTimeMillis()) { + return if (sCachedTagIndexVersion == null || + tagIndexVersionCacheTime + INDEX_VERSION_CACHE_TIME_MS < System.currentTimeMillis()) { HitomiNozomi.getIndexVersion(client, "tagindex").subscribeOn(Schedulers.io()).doOnNext { cachedTagIndexVersion = it tagIndexVersionCacheTime = System.currentTimeMillis() @@ -76,8 +80,8 @@ class Hitomi : HttpSource(), LewdSource, UrlImpo private var galleryIndexVersionCacheTime: Long = 0 private fun galleryIndexVersion(): Single { val sCachedGalleryIndexVersion = cachedGalleryIndexVersion - return if (sCachedGalleryIndexVersion == null - || galleryIndexVersionCacheTime + INDEX_VERSION_CACHE_TIME_MS < System.currentTimeMillis()) { + return if (sCachedGalleryIndexVersion == null || + galleryIndexVersionCacheTime + INDEX_VERSION_CACHE_TIME_MS < System.currentTimeMillis()) { HitomiNozomi.getIndexVersion(client, "galleriesindex").subscribeOn(Schedulers.io()).doOnNext { cachedGalleryIndexVersion = it galleryIndexVersionCacheTime = System.currentTimeMillis() @@ -307,7 +311,6 @@ class Hitomi : HttpSource(), LewdSource, UrlImpo } } - /** * Returns an observable with the updated details for a manga. Normally it's not needed to * override this method. @@ -423,5 +426,4 @@ class Hitomi : HttpSource(), LewdSource, UrlImpo SimpleDateFormat("yyyy-MM-dd HH:mm:ss'-05'", Locale.US) } } - } 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 06f1bc62c..792b145fa 100755 --- 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 @@ -2,13 +2,22 @@ package eu.kanade.tachiyomi.source.online.all import android.content.Context import android.net.Uri -import com.github.salomonbrys.kotson.* +import com.github.salomonbrys.kotson.get +import com.github.salomonbrys.kotson.nullArray +import com.github.salomonbrys.kotson.nullLong +import com.github.salomonbrys.kotson.nullObj +import com.github.salomonbrys.kotson.nullString import com.google.gson.JsonParser import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.asObservableSuccess -import eu.kanade.tachiyomi.source.model.* +import eu.kanade.tachiyomi.source.model.Filter +import eu.kanade.tachiyomi.source.model.FilterList +import eu.kanade.tachiyomi.source.model.MangasPage +import eu.kanade.tachiyomi.source.model.Page +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.LewdSource import eu.kanade.tachiyomi.source.online.UrlImportableSource @@ -30,8 +39,8 @@ class NHentai(context: Context) : HttpSource(), LewdSource { - //TODO There is currently no way to get the most popular mangas - //TODO Instead, we delegate this to the latest updates thing to avoid confusing users with an empty screen + // TODO There is currently no way to get the most popular mangas + // TODO Instead, we delegate this to the latest updates thing to avoid confusing users with an empty screen return fetchLatestUpdates(page) } @@ -39,7 +48,7 @@ class NHentai(context: Context) : HttpSource(), LewdSource { val trimmedIdQuery = query.trim().removePrefix("id:") val newQuery = if (trimmedIdQuery.toIntOrNull() ?: -1 >= 0) { @@ -246,7 +255,7 @@ class NHentai(context: Context) : HttpSource(), LewdSource("Language", SOURCE_LANG_LIST.map { it.first }.toTypedArray()) class SortFilter : Filter.Sort( @@ -305,7 +314,6 @@ class NHentai(context: Context) : HttpSource(), LewdSource>("Release Year", listOf( ReleaseYearRangeFilter(), ReleaseYearYearFilter() diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/EightMuses.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/EightMuses.kt index cc4b2313d..99aff8505 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/EightMuses.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/EightMuses.kt @@ -2,10 +2,14 @@ package eu.kanade.tachiyomi.source.online.english import android.net.Uri import com.kizitonwose.time.hours -import hu.akarnokd.rxjava.interop.RxJavaInterop import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.asObservableSuccess -import eu.kanade.tachiyomi.source.model.* +import eu.kanade.tachiyomi.source.model.Filter +import eu.kanade.tachiyomi.source.model.FilterList +import eu.kanade.tachiyomi.source.model.MangasPage +import eu.kanade.tachiyomi.source.model.Page +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.LewdSource import eu.kanade.tachiyomi.source.online.UrlImportableSource @@ -17,13 +21,18 @@ import exh.util.CachedField import exh.util.NakedTrie import exh.util.await import exh.util.urlImportFetchSearchManga +import hu.akarnokd.rxjava.interop.RxJavaInterop import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async import kotlinx.coroutines.rx2.asSingle import kotlinx.coroutines.withContext -import okhttp3.* +import okhttp3.Headers +import okhttp3.HttpUrl import okhttp3.HttpUrl.Companion.toHttpUrlOrNull +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response import org.jsoup.Jsoup import org.jsoup.nodes.Document import org.jsoup.nodes.Element diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/HBrowse.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/HBrowse.kt index 18aced414..5d34f9d05 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/HBrowse.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/HBrowse.kt @@ -4,12 +4,16 @@ import android.net.Uri import com.github.salomonbrys.kotson.array import com.github.salomonbrys.kotson.string import com.google.gson.JsonParser -import hu.akarnokd.rxjava.interop.RxJavaInterop import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.asObservable import eu.kanade.tachiyomi.network.asObservableSuccess -import eu.kanade.tachiyomi.source.model.* +import eu.kanade.tachiyomi.source.model.Filter +import eu.kanade.tachiyomi.source.model.FilterList +import eu.kanade.tachiyomi.source.model.MangasPage +import eu.kanade.tachiyomi.source.model.Page +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.LewdSource import eu.kanade.tachiyomi.source.online.UrlImportableSource @@ -23,7 +27,9 @@ import exh.search.Text import exh.util.await import exh.util.dropBlank import exh.util.urlImportFetchSearchManga +import hu.akarnokd.rxjava.interop.RxJavaInterop import info.debatty.java.stringsimilarity.Levenshtein +import kotlin.math.ceil import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async @@ -36,7 +42,6 @@ import org.jsoup.nodes.Document import org.jsoup.nodes.Element import rx.Observable import rx.schedulers.Schedulers -import kotlin.math.ceil class HBrowse : HttpSource(), LewdSource, UrlImportableSource { /** @@ -182,7 +187,6 @@ class HBrowse : HttpSource(), LewdSource, UrlIm } } - "/result" } else { "/search" diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/HentaiCafe.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/HentaiCafe.kt index 6628e391c..93177da4e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/HentaiCafe.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/HentaiCafe.kt @@ -30,7 +30,7 @@ class HentaiCafe(delegate: HttpSource) : DelegatedHttpSource(delegate), */ override val metaClass = HentaiCafeSearchMetadata::class - //Support direct URL importing + // Support direct URL importing override fun fetchSearchManga(page: Int, query: String, filters: FilterList) = urlImportFetchSearchManga(query) { super.fetchSearchManga(page, query, filters) diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Pururin.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Pururin.kt index e4f4f1b2e..3ff669f0b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Pururin.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Pururin.kt @@ -29,7 +29,7 @@ class Pururin(delegate: HttpSource) : DelegatedHttpSource(delegate), */ override val metaClass = PururinSearchMetadata::class - //Support direct URL importing + // Support direct URL importing override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable { val trimmedIdQuery = query.trim().removePrefix("id:") val newQuery = if (trimmedIdQuery.toIntOrNull() ?: -1 >= 0) { @@ -106,4 +106,4 @@ class Pururin(delegate: HttpSource) : DelegatedHttpSource(delegate), override fun mapUrlToMangaUrl(uri: Uri): String? { return "${PururinSearchMetadata.BASE_URL}/gallery/${uri.pathSegments[1]}/${uri.lastPathSegment}" } -} \ No newline at end of file +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt index df7bdb354..03a035bb1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt @@ -4,32 +4,28 @@ import android.net.Uri import com.google.gson.JsonParser import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.source.model.FilterList -import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.LewdSource import eu.kanade.tachiyomi.source.online.UrlImportableSource import eu.kanade.tachiyomi.util.system.asJsoup import exh.metadata.metadata.TsuminoSearchMetadata -import exh.metadata.metadata.TsuminoSearchMetadata.Companion.BASE_URL import exh.metadata.metadata.TsuminoSearchMetadata.Companion.TAG_TYPE_DEFAULT import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.TAG_TYPE_VIRTUAL import exh.metadata.metadata.base.RaisedTag import exh.source.DelegatedHttpSource -import exh.util.dropBlank -import exh.util.trimAll import exh.util.urlImportFetchSearchManga +import java.text.SimpleDateFormat +import java.util.Locale import org.jsoup.nodes.Document import rx.Observable -import java.text.SimpleDateFormat -import java.util.* class Tsumino(delegate: HttpSource) : DelegatedHttpSource(delegate), LewdSource, UrlImportableSource { - override val metaClass = TsuminoSearchMetadata::class; + override val metaClass = TsuminoSearchMetadata::class override val lang = "en" - //Support direct URL importing + // Support direct URL importing override fun fetchSearchManga(page: Int, query: String, filters: FilterList) = urlImportFetchSearchManga(query) { super.fetchSearchManga(page, query, filters) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/TabbedController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/TabbedController.kt index f70d2e11f..48cbda58a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/TabbedController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/TabbedController.kt @@ -7,4 +7,4 @@ interface TabbedController { fun configureTabs(tabs: TabLayout) {} fun cleanupTabs(tabs: TabLayout) {} -} \ No newline at end of file +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/holder/BaseViewHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/holder/BaseViewHolder.kt index 525902040..481262c92 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/holder/BaseViewHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/holder/BaseViewHolder.kt @@ -8,4 +8,4 @@ abstract class BaseViewHolder(view: View) : androidx.recyclerview.widget.Recycle override val containerView: View? get() = itemView -} \ No newline at end of file +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/CheckboxItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/CheckboxItem.kt index bae15e426..ade6a3e9e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/CheckboxItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/CheckboxItem.kt @@ -42,4 +42,4 @@ open class CheckboxItem(val filter: Filter.CheckBox) : AbstractFlexibleItem) : FlexibleViewHolder(view, adapter) { val check: CheckBox = itemView.findViewById(R.id.nav_view_item) } -} \ No newline at end of file +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/SelectItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/SelectItem.kt index 44649a28e..e7164d853 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/SelectItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/SelectItem.kt @@ -54,4 +54,4 @@ open class SelectItem(val filter: Filter.Select<*>) : AbstractFlexibleItem.reconfigure(): Boolean { - //Listen for change commit + // Listen for change commit asObservable() - .skip(1) //Skip first as it is emitted immediately - .take(1) //Only listen for first commit + .skip(1) // Skip first as it is emitted immediately + .take(1) // Only listen for first commit .observeOn(AndroidSchedulers.mainThread()) .subscribeUntilDestroy { - //Only listen for first change commit + // Only listen for first change commit WarnConfigureDialogController.uploadSettings(router) } - //Always return true to save changes + // Always return true to save changes return true } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/JsoupExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/JsoupExtensions.kt index 556f84e82..2dc39e109 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/util/JsoupExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/JsoupExtensions.kt @@ -23,4 +23,4 @@ fun Element.attrOrText(css: String): String { */ fun Response.asJsoup(html: String? = null): Document { return Jsoup.parse(html ?: body!!.string(), request.url.toString()) -} \ No newline at end of file +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/view/ImageViewExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/view/ImageViewExtensions.kt index f0b81ff48..69335bc5b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/view/ImageViewExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/view/ImageViewExtensions.kt @@ -16,4 +16,4 @@ fun ImageView.setVectorCompat(@DrawableRes drawable: Int, tint: Int? = null) { vector?.setTint(tint) } setImageDrawable(vector) -} \ No newline at end of file +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewGroupExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewGroupExtensions.kt index df628d445..64c71200a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewGroupExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewGroupExtensions.kt @@ -12,4 +12,4 @@ import androidx.annotation.LayoutRes */ fun ViewGroup.inflate(@LayoutRes layout: Int, attachToRoot: Boolean = false): View { return LayoutInflater.from(context).inflate(layout, this, attachToRoot) -} \ No newline at end of file +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/preference/IntListPreference.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/preference/IntListPreference.kt index 66530f50d..63b52eb2a 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/preference/IntListPreference.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/preference/IntListPreference.kt @@ -23,4 +23,4 @@ class IntListPreference @JvmOverloads constructor(context: Context, attrs: Attri defaultReturnValue } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/EHSourceHelpers.kt b/app/src/main/java/exh/EHSourceHelpers.kt index 95611eb0f..430e72954 100755 --- a/app/src/main/java/exh/EHSourceHelpers.kt +++ b/app/src/main/java/exh/EHSourceHelpers.kt @@ -53,7 +53,7 @@ private val lewdDelegatedSourceIds = SourceManager.DELEGATED_SOURCES.filter { }.map { it.value.sourceId }.sorted() // This method MUST be fast! -fun isLewdSource(source: Long) = source in 6900..6999 - || lewdDelegatedSourceIds.binarySearch(source) >= 0 +fun isLewdSource(source: Long) = source in 6900..6999 || + lewdDelegatedSourceIds.binarySearch(source) >= 0 fun Source.isEhBasedSource() = id == EH_SOURCE_ID || id == EXH_SOURCE_ID diff --git a/app/src/main/java/exh/EXHSavedSearch.kt b/app/src/main/java/exh/EXHSavedSearch.kt index dd7e43dec..5a1570664 100644 --- a/app/src/main/java/exh/EXHSavedSearch.kt +++ b/app/src/main/java/exh/EXHSavedSearch.kt @@ -2,6 +2,8 @@ package exh import eu.kanade.tachiyomi.source.model.FilterList -data class EXHSavedSearch(val name: String, - val query: String, - val filterList: FilterList) \ No newline at end of file +data class EXHSavedSearch( + val name: String, + val query: String, + val filterList: FilterList +) diff --git a/app/src/main/java/exh/GalleryAdder.kt b/app/src/main/java/exh/GalleryAdder.kt index 38bcc453d..ba9756115 100755 --- a/app/src/main/java/exh/GalleryAdder.kt +++ b/app/src/main/java/exh/GalleryAdder.kt @@ -16,20 +16,22 @@ class GalleryAdder { private val sourceManager: SourceManager by injectLazy() - fun addGallery(url: String, - fav: Boolean = false, - forceSource: UrlImportableSource? = null, - throttleFunc: () -> Unit = {}): GalleryAddEvent { + fun addGallery( + url: String, + fav: Boolean = false, + forceSource: UrlImportableSource? = null, + throttleFunc: () -> Unit = {} + ): GalleryAddEvent { XLog.d("Importing gallery (url: %s, fav: %s, forceSource: %s)...", url, fav, forceSource) try { val uri = Uri.parse(url) // Find matching source - val source = if(forceSource != null) { + val source = if (forceSource != null) { try { if (forceSource.matchesUri(uri)) forceSource else return GalleryAddEvent.Fail.UnknownType(url) - } catch(e: Exception) { + } catch (e: Exception) { XLog.e("Source URI match check error!", e) return GalleryAddEvent.Fail.UnknownType(url) } @@ -39,7 +41,7 @@ class GalleryAdder { .find { try { it.matchesUri(uri) - } catch(e: Exception) { + } catch (e: Exception) { XLog.e("Source URI match check error!", e) false } @@ -49,7 +51,7 @@ class GalleryAdder { // Map URL to manga URL val realUrl = try { source.mapUrlToMangaUrl(uri) - } catch(e: Exception) { + } catch (e: Exception) { XLog.e("Source URI map-to-manga error!", e) null } ?: return GalleryAddEvent.Fail.UnknownType(url) @@ -57,12 +59,12 @@ class GalleryAdder { // Clean URL val cleanedUrl = try { source.cleanMangaUrl(realUrl) - } catch(e: Exception) { + } catch (e: Exception) { XLog.e("Source URI clean error!", e) null } ?: return GalleryAddEvent.Fail.UnknownType(url) - //Use manga in DB if possible, otherwise, make a new manga + // Use manga in DB if possible, otherwise, make a new manga val manga = db.getManga(cleanedUrl, source.id).executeAsBlocking() ?: Manga.create(source.id).apply { this.url = cleanedUrl @@ -71,7 +73,7 @@ class GalleryAdder { // Insert created manga if not in DB before fetching details // This allows us to keep the metadata when fetching details - if(manga.id == null) { + if (manga.id == null) { db.insertManga(manga).executeAsBlocking().insertedId()?.let { manga.id = it } @@ -86,9 +88,9 @@ class GalleryAdder { db.insertManga(manga).executeAsBlocking() - //Fetch and copy chapters + // Fetch and copy chapters try { - val chapterListObs = if(source is EHentai) { + val chapterListObs = if (source is EHentai) { source.fetchChapterList(manga, throttleFunc) } else { source.fetchChapterList(manga) @@ -102,10 +104,10 @@ class GalleryAdder { } return GalleryAddEvent.Success(url, manga) - } catch(e: Exception) { + } catch (e: Exception) { XLog.w("Could not add gallery (url: $url)!", e) - if(e is EHentai.GalleryNotFoundException) { + if (e is EHentai.GalleryNotFoundException) { return GalleryAddEvent.Fail.NotFound(url) } @@ -120,21 +122,25 @@ sealed class GalleryAddEvent { abstract val galleryUrl: String open val galleryTitle: String? = null - class Success(override val galleryUrl: String, - val manga: Manga): GalleryAddEvent() { + class Success( + override val galleryUrl: String, + val manga: Manga + ) : GalleryAddEvent() { override val galleryTitle = manga.title override val logMessage = "Added gallery: $galleryTitle" } - sealed class Fail: GalleryAddEvent() { - class UnknownType(override val galleryUrl: String): Fail() { + sealed class Fail : GalleryAddEvent() { + class UnknownType(override val galleryUrl: String) : Fail() { override val logMessage = "Unknown gallery type for gallery: $galleryUrl" } - open class Error(override val galleryUrl: String, - override val logMessage: String): Fail() + open class Error( + override val galleryUrl: String, + override val logMessage: String + ) : Fail() - class NotFound(galleryUrl: String): + class NotFound(galleryUrl: String) : Error(galleryUrl, "Gallery does not exist: $galleryUrl") } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/debug/DebugFunctions.kt b/app/src/main/java/exh/debug/DebugFunctions.kt index 925fedff2..a89e6d6aa 100644 --- a/app/src/main/java/exh/debug/DebugFunctions.kt +++ b/app/src/main/java/exh/debug/DebugFunctions.kt @@ -9,20 +9,19 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.util.system.jobScheduler import exh.EH_SOURCE_ID -import exh.EXH_SOURCE_ID import exh.EXHMigrations +import exh.EXH_SOURCE_ID import exh.eh.EHentaiUpdateWorker import exh.metadata.metadata.EHentaiSearchMetadata import exh.metadata.metadata.base.getFlatMetadataForManga import exh.metadata.metadata.base.insertFlatMetadata import exh.util.await import exh.util.cancellable -import uy.kohesive.injekt.injectLazy -import kotlinx.coroutines.* import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.toList -import kotlin.coroutines.CoroutineContext +import kotlinx.coroutines.runBlocking +import uy.kohesive.injekt.injectLazy object DebugFunctions { val app: Application by injectLazy() @@ -31,7 +30,7 @@ object DebugFunctions { val sourceManager: SourceManager by injectLazy() fun forceUpgradeMigration() { - prefs.eh_lastVersionCode().set(0) + prefs.eh_lastVersionCode().set(0) EXHMigrations.upgrade(prefs) } @@ -47,7 +46,7 @@ object DebugFunctions { for (manga in allManga) { val meta = db.getFlatMetadataForManga(manga.id!!).await()?.raise() - if(meta != null) { + if (meta != null) { // remove age flag meta.aged = false db.insertFlatMetadata(meta.flatten()).await() diff --git a/app/src/main/java/exh/debug/DebugToggles.kt b/app/src/main/java/exh/debug/DebugToggles.kt index 5b3d062e8..ff2a0ee5b 100644 --- a/app/src/main/java/exh/debug/DebugToggles.kt +++ b/app/src/main/java/exh/debug/DebugToggles.kt @@ -26,4 +26,4 @@ enum class DebugToggles(val default: Boolean) { companion object { private val prefs: PreferencesHelper by injectLazy() } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/debug/SettingsDebugController.kt b/app/src/main/java/exh/debug/SettingsDebugController.kt index d0c97df00..31d1ef9c5 100644 --- a/app/src/main/java/exh/debug/SettingsDebugController.kt +++ b/app/src/main/java/exh/debug/SettingsDebugController.kt @@ -8,8 +8,12 @@ import android.widget.HorizontalScrollView import android.widget.TextView import androidx.preference.PreferenceScreen import com.afollestad.materialdialogs.MaterialDialog -import eu.kanade.tachiyomi.ui.setting.* -import eu.kanade.tachiyomi.util.preference.* +import eu.kanade.tachiyomi.ui.setting.SettingsController +import eu.kanade.tachiyomi.util.preference.defaultValue +import eu.kanade.tachiyomi.util.preference.onClick +import eu.kanade.tachiyomi.util.preference.preference +import eu.kanade.tachiyomi.util.preference.preferenceCategory +import eu.kanade.tachiyomi.util.preference.switchPreference import kotlin.reflect.KVisibility import kotlin.reflect.full.declaredFunctions @@ -41,7 +45,7 @@ class SettingsDebugController : SettingsController() { view.text = "Function returned result:\n\n$result" MaterialDialog.Builder(context) .customView(hView, true) - } catch(t: Throwable) { + } catch (t: Throwable) { view.text = "Function threw exception:\n\n${Log.getStackTraceString(t)}" MaterialDialog.Builder(context) .customView(hView, true) @@ -59,8 +63,8 @@ class SettingsDebugController : SettingsController() { title = it.name.replace('_', ' ').toLowerCase().capitalize() key = it.prefKey defaultValue = it.default - summaryOn = if(it.default) "" else MODIFIED_TEXT - summaryOff = if(it.default) MODIFIED_TEXT else "" + summaryOn = if (it.default) "" else MODIFIED_TEXT + summaryOff = if (it.default) MODIFIED_TEXT else "" } } } @@ -74,4 +78,4 @@ class SettingsDebugController : SettingsController() { companion object { private val MODIFIED_TEXT = Html.fromHtml("MODIFIED") } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/eh/EHentaiThrottleManager.kt b/app/src/main/java/exh/eh/EHentaiThrottleManager.kt index fadffa55d..9f4a13062 100644 --- a/app/src/main/java/exh/eh/EHentaiThrottleManager.kt +++ b/app/src/main/java/exh/eh/EHentaiThrottleManager.kt @@ -1,19 +1,21 @@ package exh.eh -class EHentaiThrottleManager(private val max: Int = THROTTLE_MAX, - private val inc: Int = THROTTLE_INC) { +class EHentaiThrottleManager( + private val max: Int = THROTTLE_MAX, + private val inc: Int = THROTTLE_INC +) { private var lastThrottleTime: Long = 0 var throttleTime: Long = 0 private set fun throttle() { - //Throttle requests if necessary + // Throttle requests if necessary val now = System.currentTimeMillis() val timeDiff = now - lastThrottleTime - if(timeDiff < throttleTime) + if (timeDiff < throttleTime) Thread.sleep(throttleTime - timeDiff) - if(throttleTime < max) + if (throttleTime < max) throttleTime += inc lastThrottleTime = System.currentTimeMillis() @@ -28,4 +30,4 @@ class EHentaiThrottleManager(private val max: Int = THROTTLE_MAX, const val THROTTLE_MAX = 5500 const val THROTTLE_INC = 20 } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/eh/EHentaiUpdateHelper.kt b/app/src/main/java/exh/eh/EHentaiUpdateHelper.kt index ba9e2f476..493de299f 100644 --- a/app/src/main/java/exh/eh/EHentaiUpdateHelper.kt +++ b/app/src/main/java/exh/eh/EHentaiUpdateHelper.kt @@ -8,10 +8,10 @@ import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.MangaCategory import exh.metadata.metadata.EHentaiSearchMetadata import exh.metadata.metadata.base.getFlatMetadataForManga +import java.io.File import rx.Observable import rx.Single import uy.kohesive.injekt.injectLazy -import java.io.File data class ChapterChain(val manga: Manga, val chapters: List) @@ -61,7 +61,7 @@ class EHentaiUpdateHelper(context: Context) { val chainsAsChapters = chains.flatMap { it.chapters } - if(toDiscard.isNotEmpty()) { + if (toDiscard.isNotEmpty()) { var new = false // Copy chain chapters to curChapters @@ -75,9 +75,9 @@ class EHentaiUpdateHelper(context: Context) { chain.chapters.map { chapter -> // Convert old style chapters to new style chapters if possible - if(chapter.date_upload <= 0 - && meta?.datePosted != null - && meta?.title != null) { + if (chapter.date_upload <= 0 && + meta?.datePosted != null && + meta?.title != null) { chapter.name = meta!!.title!! chapter.date_upload = meta!!.datePosted!! } @@ -92,7 +92,7 @@ class EHentaiUpdateHelper(context: Context) { if (existing != null) { existing.read = existing.read || chapter.read existing.last_page_read = existing.last_page_read.coerceAtLeast(chapter.last_page_read) - if(newLastPageRead != null && existing.last_page_read <= 0) { + if (newLastPageRead != null && existing.last_page_read <= 0) { existing.last_page_read = newLastPageRead } existing.bookmark = existing.bookmark || chapter.bookmark @@ -107,7 +107,7 @@ class EHentaiUpdateHelper(context: Context) { bookmark = chapter.bookmark last_page_read = chapter.last_page_read - if(newLastPageRead != null && last_page_read <= 0) { + if (newLastPageRead != null && last_page_read <= 0) { last_page_read = newLastPageRead } @@ -153,7 +153,7 @@ class EHentaiUpdateHelper(context: Context) { } data class GalleryEntry(val gId: String, val gToken: String) { - class Serializer: MemAutoFlushingLookupTable.EntrySerializer { + class Serializer : MemAutoFlushingLookupTable.EntrySerializer { /** * Serialize an entry as a String. */ diff --git a/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt b/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt index 4b1c8e8be..07cd0f535 100644 --- a/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt +++ b/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt @@ -20,8 +20,8 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.online.all.EHentai -import eu.kanade.tachiyomi.util.system.jobScheduler import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource +import eu.kanade.tachiyomi.util.system.jobScheduler import exh.EH_SOURCE_ID import exh.EXH_SOURCE_ID import exh.debug.DebugToggles @@ -31,18 +31,23 @@ import exh.metadata.metadata.base.getFlatMetadataForManga import exh.metadata.metadata.base.insertFlatMetadata import exh.util.await import exh.util.cancellable -import kotlinx.coroutines.* +import kotlin.coroutines.CoroutineContext +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.toList +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import rx.schedulers.Schedulers import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy -import kotlin.coroutines.CoroutineContext @RequiresApi(Build.VERSION_CODES.LOLLIPOP) -class EHentaiUpdateWorker: JobService(), CoroutineScope { +class EHentaiUpdateWorker : JobService(), CoroutineScope { override val coroutineContext: CoroutineContext get() = Dispatchers.Default + Job() @@ -215,8 +220,8 @@ class EHentaiUpdateWorker: JobService(), CoroutineScope { val (acceptedRoot, discardedRoots, hasNew) = updateHelper.findAcceptedRootAndDiscardOthers(manga.source, chapters).await() - if((new.isNotEmpty() && manga.id == acceptedRoot.manga.id) - || (hasNew && updatedManga.none { it.id == acceptedRoot.manga.id })) { + if ((new.isNotEmpty() && manga.id == acceptedRoot.manga.id) || + (hasNew && updatedManga.none { it.id == acceptedRoot.manga.id })) { updatedManga += acceptedRoot.manga } @@ -235,7 +240,7 @@ class EHentaiUpdateWorker: JobService(), CoroutineScope { ) ) - if(updatedManga.isNotEmpty()) { + if (updatedManga.isNotEmpty()) { updateNotifier.showResultNotification(updatedManga) } } @@ -254,10 +259,10 @@ class EHentaiUpdateWorker: JobService(), CoroutineScope { val newChapters = source.fetchChapterList(manga).toSingle().await(Schedulers.io()) val (new, _) = syncChaptersWithSource(db, newChapters, manga, source) // Not suspending, but does block, maybe fix this? return new to db.getChapters(manga).await() - } catch(t: Throwable) { - if(t is EHentai.GalleryNotFoundException) { + } catch (t: Throwable) { + if (t is EHentai.GalleryNotFoundException) { val meta = db.getFlatMetadataForManga(manga.id!!).await()?.raise() - if(meta != null) { + if (meta != null) { // Age dead galleries logger.d("Aged %s - notfound", manga.id) meta.aged = true @@ -286,18 +291,20 @@ class EHentaiUpdateWorker: JobService(), CoroutineScope { private fun Context.baseBackgroundJobInfo(isTest: Boolean): JobInfo.Builder { return JobInfo.Builder( - if(isTest) JOB_ID_UPDATE_BACKGROUND_TEST + if (isTest) JOB_ID_UPDATE_BACKGROUND_TEST else JOB_ID_UPDATE_BACKGROUND, componentName()) } - private fun Context.periodicBackgroundJobInfo(period: Long, - requireCharging: Boolean, - requireUnmetered: Boolean): JobInfo { + private fun Context.periodicBackgroundJobInfo( + period: Long, + requireCharging: Boolean, + requireUnmetered: Boolean + ): JobInfo { return baseBackgroundJobInfo(false) .setPeriodic(period) .setPersisted(true) .setRequiredNetworkType( - if(requireUnmetered) JobInfo.NETWORK_TYPE_UNMETERED + if (requireUnmetered) JobInfo.NETWORK_TYPE_UNMETERED else JobInfo.NETWORK_TYPE_ANY) .apply { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { @@ -321,7 +328,7 @@ class EHentaiUpdateWorker: JobService(), CoroutineScope { fun launchBackgroundTest(context: Context) { val jobScheduler = context.jobScheduler - if(jobScheduler.schedule(context.testBackgroundJobInfo()) == JobScheduler.RESULT_FAILURE) { + if (jobScheduler.schedule(context.testBackgroundJobInfo()) == JobScheduler.RESULT_FAILURE) { logger.e("Failed to schedule background test job!") } else { logger.d("Successfully scheduled background test job!") @@ -344,7 +351,7 @@ class EHentaiUpdateWorker: JobService(), CoroutineScope { wifiRestriction ) - if(context.jobScheduler.schedule(jobInfo) == JobScheduler.RESULT_FAILURE) { + if (context.jobScheduler.schedule(jobInfo) == JobScheduler.RESULT_FAILURE) { logger.e("Failed to schedule background update job!") } else { logger.d("Successfully scheduled background update job!") diff --git a/app/src/main/java/exh/eh/EHentaiUpdaterStats.kt b/app/src/main/java/exh/eh/EHentaiUpdaterStats.kt index b91854b9f..c8151063e 100644 --- a/app/src/main/java/exh/eh/EHentaiUpdaterStats.kt +++ b/app/src/main/java/exh/eh/EHentaiUpdaterStats.kt @@ -1,7 +1,7 @@ package exh.eh data class EHentaiUpdaterStats( - val startTime: Long, - val possibleUpdates: Int, - val updateCount: Int -) \ No newline at end of file + val startTime: Long, + val possibleUpdates: Int, + val updateCount: Int +) diff --git a/app/src/main/java/exh/eh/GalleryNotUpdatedException.kt b/app/src/main/java/exh/eh/GalleryNotUpdatedException.kt index 724c43e9f..feeabaf47 100644 --- a/app/src/main/java/exh/eh/GalleryNotUpdatedException.kt +++ b/app/src/main/java/exh/eh/GalleryNotUpdatedException.kt @@ -1,3 +1,3 @@ package exh.eh -class GalleryNotUpdatedException(val network: Boolean, cause: Throwable): RuntimeException(cause) \ No newline at end of file +class GalleryNotUpdatedException(val network: Boolean, cause: Throwable) : RuntimeException(cause) diff --git a/app/src/main/java/exh/eh/MemAutoFlushingLookupTable.kt b/app/src/main/java/exh/eh/MemAutoFlushingLookupTable.kt index cc1f2904c..911949289 100644 --- a/app/src/main/java/exh/eh/MemAutoFlushingLookupTable.kt +++ b/app/src/main/java/exh/eh/MemAutoFlushingLookupTable.kt @@ -3,9 +3,6 @@ package exh.eh import android.util.SparseArray import androidx.core.util.AtomicFile import com.elvishew.xlog.XLog -import kotlinx.coroutines.* -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock import java.io.Closeable import java.io.File import java.io.FileNotFoundException @@ -13,6 +10,18 @@ import java.io.InputStream import java.nio.ByteBuffer import kotlin.concurrent.thread import kotlin.coroutines.CoroutineContext +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.NonCancellable +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.cancelAndJoin +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import kotlinx.coroutines.withContext /** * In memory Int -> Obj lookup table implementation that @@ -23,9 +32,9 @@ import kotlin.coroutines.CoroutineContext * @author nulldev */ class MemAutoFlushingLookupTable( - file: File, - private val serializer: EntrySerializer, - private val debounceTimeMs: Long = 3000 + file: File, + private val serializer: EntrySerializer, + private val debounceTimeMs: Long = 3000 ) : CoroutineScope, Closeable { /** * The context of this scope. @@ -49,7 +58,7 @@ class MemAutoFlushingLookupTable( private val atomicFile = AtomicFile(file) private val shutdownHook = thread(start = false) { - if(!flushed) writeSynchronously() + if (!flushed) writeSynchronously() } init { @@ -62,9 +71,9 @@ class MemAutoFlushingLookupTable( var readIter = 0 while (true) { val readThisIter = read(targetArray, readIter, byteCount - readIter) - if(readThisIter <= 0) return false // No more data to read + if (readThisIter <= 0) return false // No more data to read readIter += readThisIter - if(readIter == byteCount) return true + if (readIter == byteCount) return true } } @@ -74,16 +83,16 @@ class MemAutoFlushingLookupTable( atomicFile.openRead().buffered().use { input -> val bb = ByteBuffer.allocate(8) - while(true) { - if(!input.requireBytes(bb.array(), 8)) break + while (true) { + if (!input.requireBytes(bb.array(), 8)) break val k = bb.getInt(0) val size = bb.getInt(4) val strBArr = ByteArray(size) - if(!input.requireBytes(strBArr, size)) break + if (!input.requireBytes(strBArr, size)) break table.put(k, serializer.read(strBArr.toString(Charsets.UTF_8))) } } - } catch(e: FileNotFoundException) { + } catch (e: FileNotFoundException) { XLog.d("Lookup table not found!", e) // Ignored } @@ -97,11 +106,11 @@ class MemAutoFlushingLookupTable( flushed = false launch { delay(debounceTimeMs) - if(id != writeCounter) return@launch + if (id != writeCounter) return@launch mutex.withLock { // Second check inside of mutex to prevent dupe writes - if(id != writeCounter) return@launch + if (id != writeCounter) return@launch withContext(NonCancellable) { writeSynchronously() @@ -118,7 +127,7 @@ class MemAutoFlushingLookupTable( val fos = atomicFile.startWrite() try { val out = fos.buffered() - for(i in 0 until table.size()) { + for (i in 0 until table.size()) { val k = table.keyAt(i) val v = serializer.write(table.valueAt(i)).toByteArray(Charsets.UTF_8) bb.putInt(0, k) @@ -128,7 +137,7 @@ class MemAutoFlushingLookupTable( } out.flush() atomicFile.finishWrite(fos) - } catch(t: Throwable) { + } catch (t: Throwable) { atomicFile.failWrite(fos) throw t } @@ -212,4 +221,4 @@ class MemAutoFlushingLookupTable( private const val INITIAL_SIZE = 1000 private const val ENTRY_SIZE_BYTES = 8 } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/favorites/FavoriteEntry.kt b/app/src/main/java/exh/favorites/FavoriteEntry.kt index 543f90501..b57edbbdb 100644 --- a/app/src/main/java/exh/favorites/FavoriteEntry.kt +++ b/app/src/main/java/exh/favorites/FavoriteEntry.kt @@ -5,7 +5,7 @@ import io.realm.RealmObject import io.realm.annotations.Index import io.realm.annotations.PrimaryKey import io.realm.annotations.RealmClass -import java.util.* +import java.util.UUID @RealmClass open class FavoriteEntry : RealmObject() { diff --git a/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt b/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt index 803d428c9..fad211303 100644 --- a/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt +++ b/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt @@ -17,18 +17,21 @@ import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.system.powerManager import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.wifiManager -import exh.* +import exh.EH_SOURCE_ID +import exh.EXH_SOURCE_ID +import exh.GalleryAddEvent +import exh.GalleryAdder import exh.eh.EHentaiThrottleManager import exh.eh.EHentaiUpdateWorker import exh.util.ignore import exh.util.trans +import kotlin.concurrent.thread import okhttp3.FormBody import okhttp3.Request import rx.subjects.BehaviorSubject import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy -import kotlin.concurrent.thread class FavoritesSyncHelper(val context: Context) { private val db: DatabaseHelper by injectLazy() @@ -55,7 +58,7 @@ class FavoritesSyncHelper(val context: Context) { @Synchronized fun runSync() { - if(status.value !is FavoritesSyncStatus.Idle) { + if (status.value !is FavoritesSyncStatus.Idle) { return } @@ -65,8 +68,8 @@ class FavoritesSyncHelper(val context: Context) { } private fun beginSync() { - //Check if logged in - if(!prefs.enableExhentai().getOrDefault()) { + // Check if logged in + if (!prefs.enableExhentai().getOrDefault()) { status.onNext(FavoritesSyncStatus.Error("Please log in!")) return } @@ -76,9 +79,9 @@ class FavoritesSyncHelper(val context: Context) { val libraryManga = db.getLibraryMangas().executeAsBlocking() val seenManga = HashSet(libraryManga.size) libraryManga.forEach { - if(it.source != EXH_SOURCE_ID && it.source != EH_SOURCE_ID) return@forEach + if (it.source != EXH_SOURCE_ID && it.source != EH_SOURCE_ID) return@forEach - if(it.id in seenManga) { + if (it.id in seenManga) { val inCategories = db.getCategoriesForManga(it).executeAsBlocking() status.onNext(FavoritesSyncStatus.BadLibraryState .MangaInMultipleCategories(it, inCategories)) @@ -89,20 +92,20 @@ class FavoritesSyncHelper(val context: Context) { } } - //Download remote favorites + // Download remote favorites val favorites = try { status.onNext(FavoritesSyncStatus.Processing("Downloading favorites from remote server")) exh.fetchFavorites() - } catch(e: Exception) { + } catch (e: Exception) { status.onNext(FavoritesSyncStatus.Error("Failed to fetch favorites from remote server!")) - logger.e( "Could not fetch favorites!", e) + logger.e("Could not fetch favorites!", e) return } val errorList = mutableListOf() try { - //Take wake + wifi locks + // Take wake + wifi locks ignore { wakeLock?.release() } wakeLock = ignore { context.powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, @@ -124,20 +127,20 @@ class FavoritesSyncHelper(val context: Context) { db.inTransaction { status.onNext(FavoritesSyncStatus.Processing("Calculating remote changes")) val remoteChanges = storage.getChangedRemoteEntries(realm, favorites.first) - val localChanges = if(prefs.eh_readOnlySync().getOrDefault()) { - null //Do not build local changes if they are not going to be applied + val localChanges = if (prefs.eh_readOnlySync().getOrDefault()) { + null // Do not build local changes if they are not going to be applied } else { status.onNext(FavoritesSyncStatus.Processing("Calculating local changes")) storage.getChangedDbEntries(realm) } - //Apply remote categories + // Apply remote categories status.onNext(FavoritesSyncStatus.Processing("Updating category names")) applyRemoteCategories(errorList, favorites.second) - //Apply change sets + // Apply change sets applyChangeSetToLocal(errorList, remoteChanges) - if(localChanges != null) + if (localChanges != null) applyChangeSetToRemote(errorList, localChanges) status.onNext(FavoritesSyncStatus.Processing("Cleaning up")) @@ -150,16 +153,16 @@ class FavoritesSyncHelper(val context: Context) { launchUI { theContext.toast("Sync complete!") } - } catch(e: IgnoredException) { - //Do not display error as this error has already been reported - logger.w( "Ignoring exception!", e) + } catch (e: IgnoredException) { + // Do not display error as this error has already been reported + logger.w("Ignoring exception!", e) return } catch (e: Exception) { status.onNext(FavoritesSyncStatus.Error("Unknown error: ${e.message}")) - logger.e( "Sync error!", e) + logger.e("Sync error!", e) return } finally { - //Release wake + wifi locks + // Release wake + wifi locks ignore { wakeLock?.release() wakeLock = null @@ -175,7 +178,7 @@ class FavoritesSyncHelper(val context: Context) { } } - if(errorList.isEmpty()) + if (errorList.isEmpty()) status.onNext(FavoritesSyncStatus.Idle()) else status.onNext(FavoritesSyncStatus.CompleteWithErrors(errorList)) @@ -195,31 +198,31 @@ class FavoritesSyncHelper(val context: Context) { Category.create(remote).apply { order = index - //Going through categories list from front to back - //If category does not exist, list size <= category index - //Thus, we can just add it here and not worry about indexing + // Going through categories list from front to back + // If category does not exist, list size <= category index + // Thus, we can just add it here and not worry about indexing newLocalCategories += this } } - if(local.name != remote) { + if (local.name != remote) { changed = true local.name = remote } } - //Ensure consistent ordering + // Ensure consistent ordering newLocalCategories.forEachIndexed { index, category -> - if(category.order != index) { + if (category.order != index) { changed = true category.order = index } } - //Only insert categories if changed - if(changed) + // Only insert categories if changed + if (changed) db.insertCategories(newLocalCategories).executeAsBlocking() } @@ -236,10 +239,10 @@ class FavoritesSyncHelper(val context: Context) { .build()) .build() - if(!explicitlyRetryExhRequest(10, request)) { - val errorString = "Unable to add gallery to remote server: '${gallery.title}' (GID: ${gallery.gid})!" + if (!explicitlyRetryExhRequest(10, request)) { + val errorString = "Unable to add gallery to remote server: '${gallery.title}' (GID: ${gallery.gid})!" - if(prefs.eh_lenientSync().getOrDefault()) { + if (prefs.eh_lenientSync().getOrDefault()) { errorList += errorString } else { status.onNext(FavoritesSyncStatus.Error(errorString)) @@ -251,7 +254,7 @@ class FavoritesSyncHelper(val context: Context) { private fun explicitlyRetryExhRequest(retryCount: Int, request: Request): Boolean { var success = false - for(i in 1 .. retryCount) { + for (i in 1..retryCount) { try { val resp = exh.client.newCall(request).execute() @@ -260,7 +263,7 @@ class FavoritesSyncHelper(val context: Context) { break } } catch (e: Exception) { - logger.w( "Sync network error!", e) + logger.w("Sync network error!", e) } } @@ -268,15 +271,15 @@ class FavoritesSyncHelper(val context: Context) { } private fun applyChangeSetToRemote(errorList: MutableList, changeSet: ChangeSet) { - //Apply removals - if(changeSet.removed.isNotEmpty()) { + // Apply removals + if (changeSet.removed.isNotEmpty()) { status.onNext(FavoritesSyncStatus.Processing("Removing ${changeSet.removed.size} galleries from remote server")) val formBody = FormBody.Builder() .add("ddact", "delete") .add("apply", "Apply") - //Add change set to form + // Add change set to form changeSet.removed.forEach { formBody.add("modifygids[]", it.gid) } @@ -286,10 +289,10 @@ class FavoritesSyncHelper(val context: Context) { .post(formBody.build()) .build() - if(!explicitlyRetryExhRequest(10, request)) { + if (!explicitlyRetryExhRequest(10, request)) { val errorString = "Unable to delete galleries from the remote servers!" - if(prefs.eh_lenientSync().getOrDefault()) { + if (prefs.eh_lenientSync().getOrDefault()) { errorList += errorString } else { status.onNext(FavoritesSyncStatus.Error(errorString)) @@ -298,7 +301,7 @@ class FavoritesSyncHelper(val context: Context) { } } - //Apply additions + // Apply additions throttleManager.resetThrottle() changeSet.added.forEachIndexed { index, it -> status.onNext(FavoritesSyncStatus.Processing("Adding gallery ${index + 1} of ${changeSet.added.size} to remote server", @@ -313,17 +316,17 @@ class FavoritesSyncHelper(val context: Context) { private fun applyChangeSetToLocal(errorList: MutableList, changeSet: ChangeSet) { val removedManga = mutableListOf() - //Apply removals + // Apply removals changeSet.removed.forEachIndexed { index, it -> status.onNext(FavoritesSyncStatus.Processing("Removing gallery ${index + 1} of ${changeSet.removed.size} from local library")) val url = it.getUrl() - //Consider both EX and EH sources + // Consider both EX and EH sources listOf(db.getManga(url, EXH_SOURCE_ID), db.getManga(url, EH_SOURCE_ID)).forEach { val manga = it.executeAsBlocking() - if(manga?.favorite == true) { + if (manga?.favorite == true) { manga.favorite = false db.updateMangaFavorite(manga).executeAsBlocking() removedManga += manga @@ -339,7 +342,7 @@ class FavoritesSyncHelper(val context: Context) { val insertedMangaCategories = mutableListOf>() val categories = db.getCategories().executeAsBlocking() - //Apply additions + // Apply additions throttleManager.resetThrottle() changeSet.added.forEachIndexed { index, it -> status.onNext(FavoritesSyncStatus.Processing("Adding gallery ${index + 1} of ${changeSet.added.size} to local library", @@ -347,14 +350,14 @@ class FavoritesSyncHelper(val context: Context) { throttleManager.throttle() - //Import using gallery adder + // Import using gallery adder val result = galleryAdder.addGallery("${exh.baseUrl}${it.getUrl()}", true, exh, throttleManager::throttle) - if(result is GalleryAddEvent.Fail) { - if(result is GalleryAddEvent.Fail.NotFound) { + if (result is GalleryAddEvent.Fail) { + if (result is GalleryAddEvent.Fail.NotFound) { XLog.e("Remote gallery does not exist, skipping: %s!", it.getUrl()) // Skip this gallery, it no longer exists return@forEachIndexed @@ -365,13 +368,13 @@ class FavoritesSyncHelper(val context: Context) { is GalleryAddEvent.Fail.UnknownType -> "'${it.title}' (${result.galleryUrl}) is not a valid gallery!" } - if(prefs.eh_lenientSync().getOrDefault()) { + if (prefs.eh_lenientSync().getOrDefault()) { errorList += errorString } else { status.onNext(FavoritesSyncStatus.Error(errorString)) throw IgnoredException() } - } else if(result is GalleryAddEvent.Success) { + } else if (result is GalleryAddEvent.Success) { insertedMangaCategories += MangaCategory.create(result.manga, categories[it.category]) to result.manga } @@ -385,8 +388,8 @@ class FavoritesSyncHelper(val context: Context) { } } - fun needWarnThrottle() - = throttleManager.throttleTime >= THROTTLE_WARN + fun needWarnThrottle() = + throttleManager.throttleTime >= THROTTLE_WARN class IgnoredException : RuntimeException() @@ -399,12 +402,14 @@ sealed class FavoritesSyncStatus(val message: String) { class Error(message: String) : FavoritesSyncStatus(message) class Idle : FavoritesSyncStatus("Waiting for sync to start") sealed class BadLibraryState(message: String) : FavoritesSyncStatus(message) { - class MangaInMultipleCategories(val manga: Manga, - val categories: List): + class MangaInMultipleCategories( + val manga: Manga, + val categories: List + ) : BadLibraryState("The gallery: ${manga.title} is in more than one category (${categories.joinToString { it.name }})!") } class Initializing : FavoritesSyncStatus("Initializing sync") - class Processing(message: String, isThrottle: Boolean = false) : FavoritesSyncStatus(if(isThrottle) + class Processing(message: String, isThrottle: Boolean = false) : FavoritesSyncStatus(if (isThrottle) "$message\n\nSync is currently throttling (to avoid being banned from ExHentai) and may take a long time to complete." else message) diff --git a/app/src/main/java/exh/favorites/LocalFavoritesStorage.kt b/app/src/main/java/exh/favorites/LocalFavoritesStorage.kt index 96e526a48..9a97d56d5 100644 --- a/app/src/main/java/exh/favorites/LocalFavoritesStorage.kt +++ b/app/src/main/java/exh/favorites/LocalFavoritesStorage.kt @@ -20,8 +20,8 @@ class LocalFavoritesStorage { fun getRealm() = Realm.getInstance(realmConfig) - fun getChangedDbEntries(realm: Realm) - = getChangedEntries(realm, + fun getChangedDbEntries(realm: Realm) = + getChangedEntries(realm, parseToFavoriteEntries( loadDbCategories( db.getFavoriteMangas() @@ -31,8 +31,8 @@ class LocalFavoritesStorage { ) ) - fun getChangedRemoteEntries(realm: Realm, entries: List) - = getChangedEntries(realm, + fun getChangedRemoteEntries(realm: Realm, entries: List) = + getChangedEntries(realm, parseToFavoriteEntries( entries.asSequence().map { Pair(it.fav, it.manga.apply { @@ -51,10 +51,10 @@ class LocalFavoritesStorage { ) ) - //Delete old snapshot + // Delete old snapshot realm.delete(FavoriteEntry::class.java) - //Insert new snapshots + // Insert new snapshots realm.copyToRealm(dbMangas.toList()) } @@ -80,18 +80,18 @@ class LocalFavoritesStorage { return ChangeSet(added, removed) } - private fun Realm.queryRealmForEntry(entry: FavoriteEntry) - = where(FavoriteEntry::class.java) + private fun Realm.queryRealmForEntry(entry: FavoriteEntry) = + where(FavoriteEntry::class.java) .equalTo(FavoriteEntry::gid.name, entry.gid) .equalTo(FavoriteEntry::token.name, entry.token) .equalTo(FavoriteEntry::category.name, entry.category) .findFirst() - private fun queryListForEntry(list: List, entry: FavoriteEntry) - = list.find { - it.gid == entry.gid - && it.token == entry.token - && it.category == entry.category + private fun queryListForEntry(list: List, entry: FavoriteEntry) = + list.find { + it.gid == entry.gid && + it.token == entry.token && + it.category == entry.category } private fun loadDbCategories(manga: Sequence): Sequence> { @@ -105,8 +105,8 @@ class LocalFavoritesStorage { } } - private fun parseToFavoriteEntries(manga: Sequence>) - = manga.filter { + private fun parseToFavoriteEntries(manga: Sequence>) = + manga.filter { validateDbManga(it.second) }.mapNotNull { FavoriteEntry().apply { @@ -115,18 +115,20 @@ class LocalFavoritesStorage { token = EHentaiSearchMetadata.galleryToken(it.second.url) category = it.first - if(this.category > MAX_CATEGORIES) + if (this.category > MAX_CATEGORIES) return@mapNotNull null } } - private fun validateDbManga(manga: Manga) - = manga.favorite && (manga.source == EH_SOURCE_ID || manga.source == EXH_SOURCE_ID) + private fun validateDbManga(manga: Manga) = + manga.favorite && (manga.source == EH_SOURCE_ID || manga.source == EXH_SOURCE_ID) companion object { const val MAX_CATEGORIES = 9 } } -data class ChangeSet(val added: List, - val removed: List) +data class ChangeSet( + val added: List, + val removed: List +) diff --git a/app/src/main/java/exh/hitomi/HitomiNozomi.kt b/app/src/main/java/exh/hitomi/HitomiNozomi.kt index 80fe9d6ad..505ca0e4e 100644 --- a/app/src/main/java/exh/hitomi/HitomiNozomi.kt +++ b/app/src/main/java/exh/hitomi/HitomiNozomi.kt @@ -4,42 +4,46 @@ import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.asObservable import eu.kanade.tachiyomi.network.asObservableSuccess import exh.metadata.metadata.HitomiSearchMetadata.Companion.LTN_BASE_URL +import java.security.MessageDigest import okhttp3.Headers import okhttp3.OkHttpClient import okhttp3.Request import org.vepta.vdm.ByteCursor import rx.Observable import rx.Single -import java.security.MessageDigest private typealias HashedTerm = ByteArray private data class DataPair(val offset: Long, val length: Int) -private data class Node(val keys: List, - val datas: List, - val subnodeAddresses: List) +private data class Node( + val keys: List, + val datas: List, + val subnodeAddresses: List +) /** * Kotlin port of the hitomi.la search algorithm * @author NerdNumber9 */ -class HitomiNozomi(private val client: OkHttpClient, - private val tagIndexVersion: Long, - private val galleriesIndexVersion: Long) { +class HitomiNozomi( + private val client: OkHttpClient, + private val tagIndexVersion: Long, + private val galleriesIndexVersion: Long +) { fun getGalleryIdsForQuery(query: String): Single> { val replacedQuery = query.replace('_', ' ') - if(':' in replacedQuery) { + if (':' in replacedQuery) { val sides = replacedQuery.split(':') val namespace = sides[0] var tag = sides[1] var area: String? = namespace var language = "all" - if(namespace == "female" || namespace == "male") { + if (namespace == "female" || namespace == "male") { area = "tag" tag = replacedQuery - } else if(namespace == "language") { + } else if (namespace == "language") { area = null language = tag tag = "index" @@ -52,7 +56,7 @@ class HitomiNozomi(private val client: OkHttpClient, val field = "galleries" return getNodeAtAddress(field, 0).flatMap { node -> - if(node == null) { + if (node == null) { Single.just(null) } else { BSearch(field, key, node).flatMap { data -> @@ -67,12 +71,12 @@ class HitomiNozomi(private val client: OkHttpClient, } private fun getGalleryIdsFromData(data: DataPair?): Single> { - if(data == null) + if (data == null) return Single.just(emptyList()) val url = "$LTN_BASE_URL/$GALLERIES_INDEX_DIR/galleries.$galleriesIndexVersion.data" val (offset, length) = data - if(length > 100000000 || length <= 0) + if (length > 100000000 || length <= 0) return Single.just(emptyList()) return client.newCall(rangedGet(url, offset, offset + length - 1)) @@ -82,7 +86,7 @@ class HitomiNozomi(private val client: OkHttpClient, } .onErrorReturn { ByteArray(0) } .map { inbuf -> - if(inbuf.isEmpty()) + if (inbuf.isEmpty()) return@map emptyList() val view = ByteCursor(inbuf) @@ -90,13 +94,13 @@ class HitomiNozomi(private val client: OkHttpClient, val expectedLength = numberOfGalleryIds * 4 + 4 - if(numberOfGalleryIds > 10000000 - || numberOfGalleryIds <= 0 - || inbuf.size != expectedLength) { + if (numberOfGalleryIds > 10000000 || + numberOfGalleryIds <= 0 || + inbuf.size != expectedLength) { return@map emptyList() } - (1 .. numberOfGalleryIds).map { + (1..numberOfGalleryIds).map { view.nextInt() } }.toSingle() @@ -105,12 +109,12 @@ class HitomiNozomi(private val client: OkHttpClient, private fun BSearch(field: String, key: ByteArray, node: Node?): Single { fun compareByteArrays(dv1: ByteArray, dv2: ByteArray): Int { val top = Math.min(dv1.size, dv2.size) - for(i in 0 until top) { + for (i in 0 until top) { val dv1i = dv1[i].toInt() and 0xFF val dv2i = dv2[i].toInt() and 0xFF - if(dv1i < dv2i) + if (dv1i < dv2i) return -1 - else if(dv1i > dv2i) + else if (dv1i > dv2i) return 1 } return 0 @@ -119,9 +123,9 @@ class HitomiNozomi(private val client: OkHttpClient, fun locateKey(key: ByteArray, node: Node): Pair { var cmpResult = -1 var lastI = 0 - for(nodeKey in node.keys) { + for (nodeKey in node.keys) { cmpResult = compareByteArrays(key, nodeKey) - if(cmpResult <= 0) break + if (cmpResult <= 0) break lastI++ } return (cmpResult == 0) to lastI @@ -133,14 +137,14 @@ class HitomiNozomi(private val client: OkHttpClient, } } - if(node == null || node.keys.isEmpty()) { + if (node == null || node.keys.isEmpty()) { return Single.just(null) } val (there, where) = locateKey(key, node) - if(there) { + if (there) { return Single.just(node.datas[where]) - } else if(isLeaf(node)) { + } else if (isLeaf(node)) { return Single.just(null) } @@ -154,20 +158,20 @@ class HitomiNozomi(private val client: OkHttpClient, val numberOfKeys = view.nextInt() - val keys = (1 .. numberOfKeys).map { + val keys = (1..numberOfKeys).map { val keySize = view.nextInt() view.next(keySize) } val numberOfDatas = view.nextInt() - val datas = (1 .. numberOfDatas).map { + val datas = (1..numberOfDatas).map { val offset = view.nextLong() val length = view.nextInt() DataPair(offset, length) } val numberOfSubnodeAddresses = B + 1 - val subnodeAddresses = (1 .. numberOfSubnodeAddresses).map { + val subnodeAddresses = (1..numberOfSubnodeAddresses).map { view.nextLong() } @@ -176,7 +180,7 @@ class HitomiNozomi(private val client: OkHttpClient, private fun getNodeAtAddress(field: String, address: Long): Single { var url = "$LTN_BASE_URL/$INDEX_DIR/$field.$tagIndexVersion.index" - if(field == "galleries") { + if (field == "galleries") { url = "$LTN_BASE_URL/$GALLERIES_INDEX_DIR/galleries.$galleriesIndexVersion.index" } @@ -187,7 +191,7 @@ class HitomiNozomi(private val client: OkHttpClient, } .onErrorReturn { ByteArray(0) } .map { nodedata -> - if(nodedata.isNotEmpty()) { + if (nodedata.isNotEmpty()) { decodeNode(nodedata) } else null }.toSingle() @@ -195,7 +199,7 @@ class HitomiNozomi(private val client: OkHttpClient, fun getGalleryIdsFromNozomi(area: String?, tag: String, language: String): Single> { var nozomiAddress = "$LTN_BASE_URL/$COMPRESSED_NOZOMI_PREFIX/$tag-$language$NOZOMI_EXTENSION" - if(area != null) { + if (area != null) { nozomiAddress = "$LTN_BASE_URL/$COMPRESSED_NOZOMI_PREFIX/$area/$tag-$language$NOZOMI_EXTENSION" } @@ -206,7 +210,7 @@ class HitomiNozomi(private val client: OkHttpClient, .map { resp -> val body = resp.body!!.bytes() val cursor = ByteCursor(body) - (1 .. body.size / 4).map { + (1..body.size / 4).map { cursor.nextInt() } }.toSingle() @@ -234,11 +238,10 @@ class HitomiNozomi(private val client: OkHttpClient, .build()) } - fun getIndexVersion(httpClient: OkHttpClient, name: String): Observable { return httpClient.newCall(GET("$LTN_BASE_URL/$name/version?_=${System.currentTimeMillis()}")) .asObservableSuccess() .map { it.body!!.string().toLong() } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/log/CrashlyticsPrinter.kt b/app/src/main/java/exh/log/CrashlyticsPrinter.kt index 61aa333b0..9ebb90d5c 100644 --- a/app/src/main/java/exh/log/CrashlyticsPrinter.kt +++ b/app/src/main/java/exh/log/CrashlyticsPrinter.kt @@ -9,17 +9,17 @@ class CrashlyticsPrinter(private val logLevel: Int) : Printer { * Print log in new line. * * @param logLevel the level of log - * @param tag the tag of log - * @param msg the msg of log + * @param tag the tag of log + * @param msg the msg of log */ override fun println(logLevel: Int, tag: String?, msg: String?) { - if(logLevel >= this.logLevel) { + if (logLevel >= this.logLevel) { try { Crashlytics.log(logLevel, tag, msg) } catch (t: Throwable) { // Crash in debug if shit like this happens - if(BuildConfig.DEBUG) throw t + if (BuildConfig.DEBUG) throw t } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/log/EHDebugModeOverlay.kt b/app/src/main/java/exh/log/EHDebugModeOverlay.kt index 3a4ff1fe6..550b0b812 100644 --- a/app/src/main/java/exh/log/EHDebugModeOverlay.kt +++ b/app/src/main/java/exh/log/EHDebugModeOverlay.kt @@ -4,11 +4,11 @@ import android.content.Context import android.text.Html import android.view.View import android.view.ViewGroup +import android.widget.LinearLayout +import android.widget.TextView import com.ms_square.debugoverlay.DataObserver import com.ms_square.debugoverlay.OverlayModule import eu.kanade.tachiyomi.BuildConfig -import android.widget.LinearLayout -import android.widget.TextView import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault @@ -61,5 +61,5 @@ class EHDebugModeOverlay(private val context: Context) : OverlayModule(n Source blacklist: ${prefs.eh_enableSourceBlacklist().getOrDefault().asEnabledString()} """.trimIndent() - private fun Boolean.asEnabledString() = if(this) "enabled" else "disabled" -} \ No newline at end of file + private fun Boolean.asEnabledString() = if (this) "enabled" else "disabled" +} diff --git a/app/src/main/java/exh/log/EHLogLevel.kt b/app/src/main/java/exh/log/EHLogLevel.kt index 65b892b07..1c9213361 100644 --- a/app/src/main/java/exh/log/EHLogLevel.kt +++ b/app/src/main/java/exh/log/EHLogLevel.kt @@ -23,4 +23,4 @@ enum class EHLogLevel(val description: String) { return curLogLevel!! >= requiredLogLevel.ordinal } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/log/EHNetworkLogging.kt b/app/src/main/java/exh/log/EHNetworkLogging.kt index d2dd4a362..21ceec7a2 100644 --- a/app/src/main/java/exh/log/EHNetworkLogging.kt +++ b/app/src/main/java/exh/log/EHNetworkLogging.kt @@ -2,7 +2,7 @@ package exh.log import okhttp3.OkHttpClient -fun OkHttpClient.Builder.maybeInjectEHLogger(): OkHttpClient.Builder { //TODO - un-break this +fun OkHttpClient.Builder.maybeInjectEHLogger(): OkHttpClient.Builder { // TODO - un-break this /* if(false &&EHLogLevel.shouldLog(EHLogLevel.EXTREME)) { val xLogger = XLog.tag("EHNetwork") .nst() diff --git a/app/src/main/java/exh/metadata/MetadataUtil.kt b/app/src/main/java/exh/metadata/MetadataUtil.kt index 8b7ad60ce..a4fd81e6d 100755 --- a/app/src/main/java/exh/metadata/MetadataUtil.kt +++ b/app/src/main/java/exh/metadata/MetadataUtil.kt @@ -1,7 +1,7 @@ package exh.metadata import java.text.SimpleDateFormat -import java.util.* +import java.util.Locale /** * Metadata utils @@ -35,13 +35,12 @@ fun parseHumanReadableByteCount(arg0: String): Double? { return null } - -fun String?.nullIfBlank(): String? = if(isNullOrBlank()) +fun String?.nullIfBlank(): String? = if (isNullOrBlank()) null else this -fun Set>.forEach(action: (K, V) -> Unit) { +fun Set>.forEach(action: (K, V) -> Unit) { forEach { action(it.key, it.value) } } diff --git a/app/src/main/java/exh/metadata/metadata/EHentaiSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/EHentaiSearchMetadata.kt index b1bf50242..053938f65 100644 --- a/app/src/main/java/exh/metadata/metadata/EHentaiSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/EHentaiSearchMetadata.kt @@ -4,12 +4,14 @@ import android.net.Uri import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.source.model.SManga -import exh.metadata.* +import exh.metadata.EX_DATE_FORMAT +import exh.metadata.ONGOING_SUFFIX +import exh.metadata.humanReadableByteCount import exh.metadata.metadata.base.RaisedSearchMetadata import exh.plusAssign +import java.util.Date import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get -import java.util.* class EHentaiSearchMetadata : RaisedSearchMetadata() { var gId: String? @@ -27,7 +29,7 @@ class EHentaiSearchMetadata : RaisedSearchMetadata() { var datePosted: Long? = null var parent: String? = null - var visible: String? = null //Not a boolean + var visible: String? = null // Not a boolean var language: String? = null var translated: Boolean? = null var size: Long? = null @@ -47,23 +49,23 @@ class EHentaiSearchMetadata : RaisedSearchMetadata() { } thumbnailUrl?.let { manga.thumbnail_url = it } - //No title bug? - val titleObj = if(Injekt.get().useJapaneseTitle().getOrDefault()) + // No title bug? + val titleObj = if (Injekt.get().useJapaneseTitle().getOrDefault()) altTitle ?: title else title titleObj?.let { manga.title = it } - //Set artist (if we can find one) + // Set artist (if we can find one) tags.filter { it.namespace == EH_ARTIST_NAMESPACE }.let { - if(it.isNotEmpty()) manga.artist = it.joinToString(transform = { it.name }) + if (it.isNotEmpty()) manga.artist = it.joinToString(transform = { it.name }) } - //Copy tags -> genres + // Copy tags -> genres manga.genre = tagsToGenreString() - //Try to automatically identify if it is ongoing, we try not to be too lenient here to avoid making mistakes - //We default to completed + // Try to automatically identify if it is ongoing, we try not to be too lenient here to avoid making mistakes + // We default to completed manga.status = SManga.COMPLETED title?.let { t -> ONGOING_SUFFIX.find { @@ -73,7 +75,7 @@ class EHentaiSearchMetadata : RaisedSearchMetadata() { } } - //Build a nice looking description out of what we know + // Build a nice looking description out of what we know val titleDesc = StringBuilder() title?.let { titleDesc += "Title: $it\n" } altTitle?.let { titleDesc += "Alternate Title: $it\n" } @@ -85,7 +87,7 @@ class EHentaiSearchMetadata : RaisedSearchMetadata() { visible?.let { detailsDesc += "Visible: $it\n" } language?.let { detailsDesc += "Language: $it" - if(translated == true) detailsDesc += " TR" + if (translated == true) detailsDesc += " TR" detailsDesc += "\n" } size?.let { detailsDesc += "File size: ${humanReadableByteCount(it, true)}\n" } @@ -114,10 +116,10 @@ class EHentaiSearchMetadata : RaisedSearchMetadata() { const val EH_GENRE_NAMESPACE = "genre" private const val EH_ARTIST_NAMESPACE = "artist" - private fun splitGalleryUrl(url: String) - = url.let { - //Only parse URL if is full URL - val pathSegments = if(it.startsWith("http")) + private fun splitGalleryUrl(url: String) = + url.let { + // Only parse URL if is full URL + val pathSegments = if (it.startsWith("http")) Uri.parse(it).pathSegments else it.split('/') @@ -129,10 +131,10 @@ class EHentaiSearchMetadata : RaisedSearchMetadata() { fun galleryToken(url: String) = splitGalleryUrl(url)[2] - fun normalizeUrl(url: String) - = idAndTokenToUrl(galleryId(url), galleryToken(url)) + fun normalizeUrl(url: String) = + idAndTokenToUrl(galleryId(url), galleryToken(url)) - fun idAndTokenToUrl(id: String, token: String) - = "/g/$id/$token/?nw=always" + fun idAndTokenToUrl(id: String, token: String) = + "/g/$id/$token/?nw=always" } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/metadata/metadata/EightMusesSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/EightMusesSearchMetadata.kt index fb35708b9..68749333c 100644 --- a/app/src/main/java/exh/metadata/metadata/EightMusesSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/EightMusesSearchMetadata.kt @@ -34,7 +34,6 @@ class EightMusesSearchMetadata : RaisedSearchMetadata() { manga.description = listOf(titleDesc.toString(), tagsDesc.toString()) .filter(String::isNotBlank) .joinToString(separator = "\n") - } companion object { @@ -47,4 +46,4 @@ class EightMusesSearchMetadata : RaisedSearchMetadata() { const val TAGS_NAMESPACE = "tags" const val ARTIST_NAMESPACE = "artist" } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/metadata/metadata/HBrowseSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/HBrowseSearchMetadata.kt index 6bad5fcfb..0083bfb70 100644 --- a/app/src/main/java/exh/metadata/metadata/HBrowseSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/HBrowseSearchMetadata.kt @@ -21,7 +21,7 @@ class HBrowseSearchMetadata : RaisedSearchMetadata() { } // Guess thumbnail URL if manga does not have thumbnail URL - if(manga.thumbnail_url.isNullOrBlank()) { + if (manga.thumbnail_url.isNullOrBlank()) { manga.thumbnail_url = guessThumbnailUrl(hbId.toString()) } @@ -49,4 +49,4 @@ class HBrowseSearchMetadata : RaisedSearchMetadata() { return "$BASE_URL/thumbnails/${hbid}_1.jpg#guessed" } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/metadata/metadata/HentaiCafeSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/HentaiCafeSearchMetadata.kt index 7ba0d6dda..0d8c2f9ab 100644 --- a/app/src/main/java/exh/metadata/metadata/HentaiCafeSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/HentaiCafeSearchMetadata.kt @@ -27,7 +27,7 @@ class HentaiCafeSearchMetadata : RaisedSearchMetadata() { manga.artist = artist manga.author = artist - //Not available + // Not available manga.status = SManga.UNKNOWN val detailsDesc = "Title: $title\n" + @@ -49,7 +49,7 @@ class HentaiCafeSearchMetadata : RaisedSearchMetadata() { const val BASE_URL = "https://hentai.cafe" - fun hcIdFromUrl(url: String) - = url.split("/").last { it.isNotBlank() } + fun hcIdFromUrl(url: String) = + url.split("/").last { it.isNotBlank() } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/metadata/metadata/HitomiSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/HitomiSearchMetadata.kt index 985e3e2d4..7f9b1603d 100644 --- a/app/src/main/java/exh/metadata/metadata/HitomiSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/HitomiSearchMetadata.kt @@ -4,9 +4,9 @@ import eu.kanade.tachiyomi.source.model.SManga import exh.metadata.EX_DATE_FORMAT import exh.metadata.metadata.base.RaisedSearchMetadata import exh.plusAssign -import java.util.* +import java.util.Date -class HitomiSearchMetadata: RaisedSearchMetadata() { +class HitomiSearchMetadata : RaisedSearchMetadata() { var url get() = hlId?.let { urlFromHlId(it) } set(a) { a?.let { @@ -62,10 +62,10 @@ class HitomiSearchMetadata: RaisedSearchMetadata() { detailsDesc += "Language: ${it.capitalize()}\n" } - if(series.isNotEmpty()) + if (series.isNotEmpty()) detailsDesc += "Series: ${series.joinToString()}\n" - if(characters.isNotEmpty()) + if (characters.isNotEmpty()) detailsDesc += "Characters: ${characters.joinToString()}\n" uploadDate?.let { @@ -74,7 +74,7 @@ class HitomiSearchMetadata: RaisedSearchMetadata() { manga.status = SManga.UNKNOWN - //Copy tags -> genres + // Copy tags -> genres manga.genre = tagsToGenreString() val tagsDesc = tagsToDescription() @@ -92,10 +92,10 @@ class HitomiSearchMetadata: RaisedSearchMetadata() { const val LTN_BASE_URL = "https://ltn.hitomi.la" const val BASE_URL = "https://hitomi.la" - fun hlIdFromUrl(url: String) - = url.split('/').last().split('-').last().substringBeforeLast('.') + fun hlIdFromUrl(url: String) = + url.split('/').last().split('-').last().substringBeforeLast('.') - fun urlFromHlId(id: String) - = "$BASE_URL/galleries/$id.html" + fun urlFromHlId(id: String) = + "$BASE_URL/galleries/$id.html" } } diff --git a/app/src/main/java/exh/metadata/metadata/NHentaiSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/NHentaiSearchMetadata.kt index b310c661f..8288484f2 100644 --- a/app/src/main/java/exh/metadata/metadata/NHentaiSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/NHentaiSearchMetadata.kt @@ -3,12 +3,14 @@ package exh.metadata.metadata import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.source.model.SManga -import exh.metadata.* +import exh.metadata.EX_DATE_FORMAT +import exh.metadata.ONGOING_SUFFIX import exh.metadata.metadata.base.RaisedSearchMetadata +import exh.metadata.nullIfBlank import exh.plusAssign +import java.util.Date import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get -import java.util.* class NHentaiSearchMetadata : RaisedSearchMetadata() { var url get() = nhId?.let { BASE_URL + nhIdToPath(it) } @@ -39,10 +41,10 @@ class NHentaiSearchMetadata : RaisedSearchMetadata() { override fun copyTo(manga: SManga) { nhId?.let { manga.url = nhIdToPath(it) } - if(mediaId != null) { + if (mediaId != null) { val hqThumbs = Injekt.get().eh_nh_useHighQualityThumbs().getOrDefault() - typeToExtension(if(hqThumbs) coverImageType else thumbnailImageType)?.let { - manga.thumbnail_url = "https://t.nhentai.net/galleries/$mediaId/${if(hqThumbs) + typeToExtension(if (hqThumbs) coverImageType else thumbnailImageType)?.let { + manga.thumbnail_url = "https://t.nhentai.net/galleries/$mediaId/${if (hqThumbs) "cover" else "thumb"}.$it" } @@ -50,21 +52,21 @@ class NHentaiSearchMetadata : RaisedSearchMetadata() { manga.title = englishTitle ?: japaneseTitle ?: shortTitle!! - //Set artist (if we can find one) + // Set artist (if we can find one) tags.filter { it.namespace == NHENTAI_ARTIST_NAMESPACE }.let { - if(it.isNotEmpty()) manga.artist = it.joinToString(transform = { it.name }) + if (it.isNotEmpty()) manga.artist = it.joinToString(transform = { it.name }) } var category: String? = null tags.filter { it.namespace == NHENTAI_CATEGORIES_NAMESPACE }.let { - if(it.isNotEmpty()) category = it.joinToString(transform = { it.name }) + if (it.isNotEmpty()) category = it.joinToString(transform = { it.name }) } - //Copy tags -> genres + // Copy tags -> genres manga.genre = tagsToGenreString() - //Try to automatically identify if it is ongoing, we try not to be too lenient here to avoid making mistakes - //We default to completed + // Try to automatically identify if it is ongoing, we try not to be too lenient here to avoid making mistakes + // We default to completed manga.status = SManga.COMPLETED englishTitle?.let { t -> ONGOING_SUFFIX.find { @@ -106,14 +108,14 @@ class NHentaiSearchMetadata : RaisedSearchMetadata() { private const val NHENTAI_CATEGORIES_NAMESPACE = "category" fun typeToExtension(t: String?) = - when(t) { + when (t) { "p" -> "png" "j" -> "jpg" else -> null } - fun nhUrlToId(url: String) - = url.split("/").last { it.isNotBlank() }.toLong() + fun nhUrlToId(url: String) = + url.split("/").last { it.isNotBlank() }.toLong() fun nhIdToPath(id: Long) = "/g/$id/" } diff --git a/app/src/main/java/exh/metadata/metadata/PervEdenSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/PervEdenSearchMetadata.kt index 9a0878dec..1223cd553 100644 --- a/app/src/main/java/exh/metadata/metadata/PervEdenSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/PervEdenSearchMetadata.kt @@ -41,7 +41,7 @@ class PervEdenSearchMetadata : RaisedSearchMetadata() { manga.title = it titleDesc += "Title: $it\n" } - if(altTitles.isNotEmpty()) + if (altTitles.isNotEmpty()) titleDesc += "Alternate Titles: \n" + altTitles .joinToString(separator = "\n", postfix = "\n") { "â–ª $it" @@ -58,7 +58,7 @@ class PervEdenSearchMetadata : RaisedSearchMetadata() { } status?.let { - manga.status = when(it) { + manga.status = when (it) { "Ongoing" -> SManga.ONGOING "Completed", "Suspended" -> SManga.COMPLETED else -> SManga.UNKNOWN @@ -70,7 +70,7 @@ class PervEdenSearchMetadata : RaisedSearchMetadata() { detailsDesc += "Rating: %.2\n".format(it) } - //Copy tags -> genres + // Copy tags -> genres manga.genre = tagsToGenreString() val tagsDesc = tagsToDescription() @@ -80,15 +80,14 @@ class PervEdenSearchMetadata : RaisedSearchMetadata() { .joinToString(separator = "\n") } - companion object { private const val TITLE_TYPE_MAIN = 0 private const val TITLE_TYPE_ALT = 1 const val TAG_TYPE_DEFAULT = 0 - private fun splitGalleryUrl(url: String) - = url.let { + private fun splitGalleryUrl(url: String) = + url.let { Uri.parse(it).pathSegments.filterNot(String::isNullOrBlank) } @@ -97,13 +96,13 @@ class PervEdenSearchMetadata : RaisedSearchMetadata() { } enum class PervEdenLang(val id: Long) { - //DO NOT RENAME THESE TO CAPITAL LETTERS! The enum names are used to build URLs + // DO NOT RENAME THESE TO CAPITAL LETTERS! The enum names are used to build URLs en(PERV_EDEN_EN_SOURCE_ID), it(PERV_EDEN_IT_SOURCE_ID); companion object { - fun source(id: Long) - = values().find { it.id == id } + fun source(id: Long) = + values().find { it.id == id } ?: throw IllegalArgumentException("Unknown source ID: $id!") } } diff --git a/app/src/main/java/exh/metadata/metadata/PururinSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/PururinSearchMetadata.kt index 762abdec7..930465c08 100644 --- a/app/src/main/java/exh/metadata/metadata/PururinSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/PururinSearchMetadata.kt @@ -47,7 +47,7 @@ class PururinSearchMetadata : RaisedSearchMetadata() { altTitle?.let { titleDesc += "Japanese Title: $it\n" } val detailsDesc = StringBuilder() - (uploaderDisp ?: uploader)?.let { detailsDesc += "Uploader: $it\n"} + (uploaderDisp ?: uploader)?.let { detailsDesc += "Uploader: $it\n" } pages?.let { detailsDesc += "Length: $it pages\n" } fileSize?.let { detailsDesc += "Size: $it\n" } ratingCount?.let { detailsDesc += "Rating: $averageRating ($ratingCount)\n" } @@ -69,4 +69,4 @@ class PururinSearchMetadata : RaisedSearchMetadata() { val BASE_URL = "https://pururin.io" } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/metadata/metadata/TsuminoSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/TsuminoSearchMetadata.kt index 462e63f4f..68683a858 100644 --- a/app/src/main/java/exh/metadata/metadata/TsuminoSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/TsuminoSearchMetadata.kt @@ -5,7 +5,7 @@ import eu.kanade.tachiyomi.source.model.SManga import exh.metadata.EX_DATE_FORMAT import exh.metadata.metadata.base.RaisedSearchMetadata import exh.plusAssign -import java.util.* +import java.util.Date class TsuminoSearchMetadata : RaisedSearchMetadata() { var tmId: Int? = null @@ -51,15 +51,15 @@ class TsuminoSearchMetadata : RaisedSearchMetadata() { collection?.let { detailsDesc += "Collection: $it\n" } group?.let { detailsDesc += "Group: $it\n" } val parodiesString = parody.joinToString() - if(parodiesString.isNotEmpty()) { + if (parodiesString.isNotEmpty()) { detailsDesc += "Parody: $parodiesString\n" } val charactersString = character.joinToString() - if(charactersString.isNotEmpty()) { + if (charactersString.isNotEmpty()) { detailsDesc += "Character: $charactersString\n" } - //Copy tags -> genres + // Copy tags -> genres manga.genre = tagsToGenreString() val tagsDesc = tagsToDescription() @@ -76,8 +76,8 @@ class TsuminoSearchMetadata : RaisedSearchMetadata() { val BASE_URL = "https://www.tsumino.com" - fun tmIdFromUrl(url: String) - = Uri.parse(url).lastPathSegment + fun tmIdFromUrl(url: String) = + Uri.parse(url).lastPathSegment fun mangaUrlFromId(id: String) = "/Book/Info/$id" diff --git a/app/src/main/java/exh/metadata/metadata/base/FlatMetadata.kt b/app/src/main/java/exh/metadata/metadata/base/FlatMetadata.kt index 0e6bdcdc1..b8aec0370 100644 --- a/app/src/main/java/exh/metadata/metadata/base/FlatMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/base/FlatMetadata.kt @@ -5,19 +5,19 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper import exh.metadata.sql.models.SearchMetadata import exh.metadata.sql.models.SearchTag import exh.metadata.sql.models.SearchTitle +import kotlin.reflect.KClass import rx.Completable import rx.Single -import kotlin.reflect.KClass data class FlatMetadata( - val metadata: SearchMetadata, - val tags: List, - val titles: List + val metadata: SearchMetadata, + val tags: List, + val titles: List ) { inline fun raise(): T = raise(T::class) - fun raise(clazz: KClass) - = RaisedSearchMetadata.raiseFlattenGson + fun raise(clazz: KClass) = + RaisedSearchMetadata.raiseFlattenGson .fromJson(metadata.extra, clazz.java).apply { fillBaseFields(this@FlatMetadata) } @@ -27,7 +27,7 @@ fun DatabaseHelper.getFlatMetadataForManga(mangaId: Long): PreparedOperation if (tags.isNotEmpty()) { val joinedTags = tags.joinToString(separator = " ", transform = { "<${it.name}>" }) - if(namespace != null) { + if (namespace != null) { this += "â–ª " this += namespace this += ": " @@ -125,8 +125,8 @@ abstract class RaisedSearchMetadata { * @param property the metadata for the property. * @return the property value. */ - override fun getValue(thisRef: RaisedSearchMetadata, property: KProperty<*>) - = thisRef.getTitleOfType(type) + override fun getValue(thisRef: RaisedSearchMetadata, property: KProperty<*>) = + thisRef.getTitleOfType(type) /** * Sets the value of the property for the given object. @@ -134,8 +134,8 @@ abstract class RaisedSearchMetadata { * @param property the metadata for the property. * @param value the value to set. */ - override fun setValue(thisRef: RaisedSearchMetadata, property: KProperty<*>, value: String?) - = thisRef.replaceTitleOfType(type, value) + override fun setValue(thisRef: RaisedSearchMetadata, property: KProperty<*>, value: String?) = + thisRef.replaceTitleOfType(type, value) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/metadata/metadata/base/RaisedTag.kt b/app/src/main/java/exh/metadata/metadata/base/RaisedTag.kt index 5e38d51c9..2745f1084 100644 --- a/app/src/main/java/exh/metadata/metadata/base/RaisedTag.kt +++ b/app/src/main/java/exh/metadata/metadata/base/RaisedTag.kt @@ -1,5 +1,7 @@ package exh.metadata.metadata.base -data class RaisedTag(val namespace: String?, - val name: String, - val type: Int) \ No newline at end of file +data class RaisedTag( + val namespace: String?, + val name: String, + val type: Int +) diff --git a/app/src/main/java/exh/metadata/metadata/base/RaisedTitle.kt b/app/src/main/java/exh/metadata/metadata/base/RaisedTitle.kt index 3f95c135d..bc901bc9a 100644 --- a/app/src/main/java/exh/metadata/metadata/base/RaisedTitle.kt +++ b/app/src/main/java/exh/metadata/metadata/base/RaisedTitle.kt @@ -1,6 +1,6 @@ package exh.metadata.metadata.base data class RaisedTitle( - val title: String, - val type: Int = 0 -) \ No newline at end of file + val title: String, + val type: Int = 0 +) diff --git a/app/src/main/java/exh/metadata/sql/models/SearchMetadata.kt b/app/src/main/java/exh/metadata/sql/models/SearchMetadata.kt index f0a1043cc..f74c18836 100644 --- a/app/src/main/java/exh/metadata/sql/models/SearchMetadata.kt +++ b/app/src/main/java/exh/metadata/sql/models/SearchMetadata.kt @@ -2,20 +2,20 @@ package exh.metadata.sql.models data class SearchMetadata( // Manga ID this gallery is linked to - val mangaId: Long, + val mangaId: Long, // Gallery uploader - val uploader: String?, + val uploader: String?, // Extra data attached to this metadata, in JSON format - val extra: String, + val extra: String, // Indexed extra data attached to this metadata - val indexedExtra: String?, + val indexedExtra: String?, // The version of this metadata's extra. Used to track changes to the 'extra' field's schema - val extraVersion: Int + val extraVersion: Int ) { // Transient information attached to this piece of metadata, useful for caching var transientCache: Map? = null -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/metadata/sql/models/SearchTag.kt b/app/src/main/java/exh/metadata/sql/models/SearchTag.kt index 1665fc9e4..324d1ecd0 100644 --- a/app/src/main/java/exh/metadata/sql/models/SearchTag.kt +++ b/app/src/main/java/exh/metadata/sql/models/SearchTag.kt @@ -2,17 +2,17 @@ package exh.metadata.sql.models data class SearchTag( // Tag identifier, unique - val id: Long?, + val id: Long?, // Metadata this tag is attached to - val mangaId: Long, + val mangaId: Long, // Tag namespace - val namespace: String?, + val namespace: String?, // Tag name - val name: String, + val name: String, // Tag type - val type: Int -) \ No newline at end of file + val type: Int +) diff --git a/app/src/main/java/exh/metadata/sql/models/SearchTitle.kt b/app/src/main/java/exh/metadata/sql/models/SearchTitle.kt index 521cccb6d..ff43b0a68 100644 --- a/app/src/main/java/exh/metadata/sql/models/SearchTitle.kt +++ b/app/src/main/java/exh/metadata/sql/models/SearchTitle.kt @@ -2,14 +2,14 @@ package exh.metadata.sql.models data class SearchTitle( // Title identifier, unique - val id: Long?, + val id: Long?, // Metadata this title is attached to - val mangaId: Long, + val mangaId: Long, // Title - val title: String, + val title: String, // Title type, useful for distinguishing between main/alt titles - val type: Int + val type: Int ) diff --git a/app/src/main/java/exh/metadata/sql/queries/SearchMetadataQueries.kt b/app/src/main/java/exh/metadata/sql/queries/SearchMetadataQueries.kt index bea55e509..17ce53710 100755 --- a/app/src/main/java/exh/metadata/sql/queries/SearchMetadataQueries.kt +++ b/app/src/main/java/exh/metadata/sql/queries/SearchMetadataQueries.kt @@ -3,7 +3,6 @@ package exh.metadata.sql.queries import com.pushtorefresh.storio.sqlite.queries.DeleteQuery import com.pushtorefresh.storio.sqlite.queries.Query import eu.kanade.tachiyomi.data.database.DbProvider -import eu.kanade.tachiyomi.data.database.models.Manga import exh.metadata.sql.models.SearchMetadata import exh.metadata.sql.tables.SearchMetadataTable @@ -42,4 +41,4 @@ interface SearchMetadataQueries : DbProvider { .table(SearchMetadataTable.TABLE) .build()) .prepare() -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/metadata/sql/queries/SearchTagQueries.kt b/app/src/main/java/exh/metadata/sql/queries/SearchTagQueries.kt index 0459cc1ac..b681ceab2 100755 --- a/app/src/main/java/exh/metadata/sql/queries/SearchTagQueries.kt +++ b/app/src/main/java/exh/metadata/sql/queries/SearchTagQueries.kt @@ -44,4 +44,4 @@ interface SearchTagQueries : DbProvider { } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/metadata/sql/queries/SearchTitleQueries.kt b/app/src/main/java/exh/metadata/sql/queries/SearchTitleQueries.kt index 291abdc76..30108faaa 100755 --- a/app/src/main/java/exh/metadata/sql/queries/SearchTitleQueries.kt +++ b/app/src/main/java/exh/metadata/sql/queries/SearchTitleQueries.kt @@ -4,8 +4,6 @@ import com.pushtorefresh.storio.sqlite.queries.DeleteQuery import com.pushtorefresh.storio.sqlite.queries.Query import eu.kanade.tachiyomi.data.database.DbProvider import eu.kanade.tachiyomi.data.database.inTransaction -import eu.kanade.tachiyomi.data.database.models.Manga -import exh.metadata.sql.models.SearchMetadata import exh.metadata.sql.models.SearchTitle import exh.metadata.sql.tables.SearchTitleTable @@ -46,4 +44,4 @@ interface SearchTitleQueries : DbProvider { } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/patch/UniversalCaptchaDetection.kt b/app/src/main/java/exh/patch/UniversalCaptchaDetection.kt index 4e74ef5f5..87cc19016 100644 --- a/app/src/main/java/exh/patch/UniversalCaptchaDetection.kt +++ b/app/src/main/java/exh/patch/UniversalCaptchaDetection.kt @@ -7,7 +7,7 @@ import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get val CAPTCHA_DETECTION_PATCH: EHInterceptor = { request, response, sourceId -> - if(!response.isSuccessful) { + if (!response.isSuccessful) { response.interceptAsHtml { doc -> // Find captcha if (doc.getElementsByClass("g-recaptcha").isNotEmpty()) { @@ -20,4 +20,4 @@ val CAPTCHA_DETECTION_PATCH: EHInterceptor = { request, response, sourceId -> } } } else response -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/search/Namespace.kt b/app/src/main/java/exh/search/Namespace.kt index e23a0e722..0e6faae48 100755 --- a/app/src/main/java/exh/search/Namespace.kt +++ b/app/src/main/java/exh/search/Namespace.kt @@ -1,4 +1,6 @@ package exh.search -class Namespace(var namespace: String, - var tag: Text? = null) : QueryComponent() +class Namespace( + var namespace: String, + var tag: Text? = null +) : QueryComponent() diff --git a/app/src/main/java/exh/search/QueryComponent.kt b/app/src/main/java/exh/search/QueryComponent.kt index bfc34eea0..387ad86c2 100755 --- a/app/src/main/java/exh/search/QueryComponent.kt +++ b/app/src/main/java/exh/search/QueryComponent.kt @@ -3,4 +3,4 @@ package exh.search open class QueryComponent { var excluded = false var exact = false -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/search/SearchEngine.kt b/app/src/main/java/exh/search/SearchEngine.kt index 5cecac007..8299d6628 100755 --- a/app/src/main/java/exh/search/SearchEngine.kt +++ b/app/src/main/java/exh/search/SearchEngine.kt @@ -7,8 +7,10 @@ import exh.metadata.sql.tables.SearchTitleTable class SearchEngine { private val queryCache = mutableMapOf>() - fun textToSubQueries(namespace: String?, - component: Text?): Pair>? { + fun textToSubQueries( + namespace: String?, + component: Text? + ): Pair>? { val maybeLenientComponent = component?.let { if (!it.exact) it.asLenientTagQueries() @@ -22,20 +24,20 @@ class SearchEngine { "${SearchTagTable.TABLE}.${SearchTagTable.COL_NAME} LIKE ?" }.joinToString(separator = " OR ", prefix = "(", postfix = ")") to params } - return if(namespace != null) { + return if (namespace != null) { var query = """ (SELECT ${SearchTagTable.COL_MANGA_ID} AS $COL_MANGA_ID FROM ${SearchTagTable.TABLE} WHERE ${SearchTagTable.COL_NAMESPACE} IS NOT NULL AND ${SearchTagTable.COL_NAMESPACE} LIKE ? """.trimIndent() val params = mutableListOf(escapeLike(namespace)) - if(componentTagQuery != null) { + if (componentTagQuery != null) { query += "\n AND ${componentTagQuery.first}" params += componentTagQuery.second } "$query)" to params - } else if(component != null) { + } else if (component != null) { // Match title + tags val tagQuery = """ SELECT ${SearchTagTable.COL_MANGA_ID} AS $COL_MANGA_ID FROM ${SearchTagTable.TABLE} @@ -59,27 +61,27 @@ class SearchEngine { val include = mutableListOf>>() val exclude = mutableListOf>>() - for(component in q) { - val query = if(component is Text) { + for (component in q) { + val query = if (component is Text) { textToSubQueries(null, component) - } else if(component is Namespace) { - if(component.namespace == "uploader") { + } else if (component is Namespace) { + if (component.namespace == "uploader") { wheres += "meta.${SearchMetadataTable.COL_UPLOADER} LIKE ?" whereParams += component.tag!!.rawTextEscapedForLike() null } else { - if(component.tag!!.components.size > 0) { - //Match namespace + tags + if (component.tag!!.components.size > 0) { + // Match namespace + tags textToSubQueries(component.namespace, component.tag) } else { - //Perform namespace search + // Perform namespace search textToSubQueries(component.namespace, null) } } } else error("Unknown query component!") - if(query != null) { - (if(component.excluded) exclude else include) += query + if (query != null) { + (if (component.excluded) exclude else include) += query } } @@ -97,14 +99,13 @@ class SearchEngine { completeParams += pair.second } - exclude.forEach { wheres += """ (meta.${SearchMetadataTable.COL_MANGA_ID} NOT IN ${it.first}) """.trimIndent() whereParams += it.second } - if(wheres.isNotEmpty()) { + if (wheres.isNotEmpty()) { completeParams += whereParams baseQuery += "\nWHERE\n" baseQuery += wheres.joinToString("\nAND\n") @@ -126,7 +127,7 @@ class SearchEngine { var nextIsExact = false fun flushText() { - if(queuedRawText.isNotEmpty()) { + if (queuedRawText.isNotEmpty()) { queuedText += StringTextComponent(queuedRawText.toString()) queuedRawText.setLength(0) } @@ -150,24 +151,24 @@ class SearchEngine { } } - for(char in query.toLowerCase()) { - if(char == '"') { + for (char in query.toLowerCase()) { + if (char == '"') { inQuotes = !inQuotes - } else if(enableWildcard && (char == '?' || char == '_')) { + } else if (enableWildcard && (char == '?' || char == '_')) { flushText() queuedText.add(SingleWildcard(char.toString())) - } else if(enableWildcard && (char == '*' || char == '%')) { + } else if (enableWildcard && (char == '*' || char == '%')) { flushText() queuedText.add(MultiWildcard(char.toString())) - } else if(char == '-') { + } else if (char == '-') { nextIsExcluded = true - } else if(char == '$') { + } else if (char == '$') { nextIsExact = true - } else if(char == ':') { + } else if (char == ':') { flushText() var flushed = flushToText().rawTextOnly() - //Map tag aliases - flushed = when(flushed) { + // Map tag aliases + flushed = when (flushed) { "a" -> "artist" "c", "char" -> "character" "f" -> "female" @@ -179,7 +180,7 @@ class SearchEngine { else -> flushed } namespace = Namespace(flushed, null) - } else if(char == ' ' && !inQuotes) { + } else if (char == ' ' && !inQuotes) { flushAll() } else { queuedRawText.append(char) @@ -197,7 +198,6 @@ class SearchEngine { return string.replace("\\", "\\\\") .replace("_", "\\_") .replace("%", "\\%") - } } } diff --git a/app/src/main/java/exh/search/Text.kt b/app/src/main/java/exh/search/Text.kt index 21638befd..2c0abd845 100755 --- a/app/src/main/java/exh/search/Text.kt +++ b/app/src/main/java/exh/search/Text.kt @@ -3,7 +3,7 @@ package exh.search import exh.plusAssign import exh.search.SearchEngine.Companion.escapeLike -class Text: QueryComponent() { +class Text : QueryComponent() { val components = mutableListOf() private var query: String? = null @@ -12,26 +12,26 @@ class Text: QueryComponent() { private var rawText: String? = null fun asQuery(): String { - if(query == null) { + if (query == null) { query = rBaseBuilder().toString() } return query!! } fun asLenientTitleQuery(): String { - if(lenientTitleQuery == null) { + if (lenientTitleQuery == null) { lenientTitleQuery = StringBuilder("%").append(rBaseBuilder()).append("%").toString() } return lenientTitleQuery!! } fun asLenientTagQueries(): List { - if(lenientTagQueries == null) { + if (lenientTagQueries == null) { lenientTagQueries = listOf( - //Match beginning of tag + // Match beginning of tag rBaseBuilder().append("%").toString(), - //Tag word matcher (that matches multiple words) - //Can't make it match a single word in Realm :( + // Tag word matcher (that matches multiple words) + // Can't make it match a single word in Realm :( StringBuilder(" ").append(rBaseBuilder()).append(" ").toString(), StringBuilder(" ").append(rBaseBuilder()).toString(), rBaseBuilder().append(" ").toString() @@ -42,8 +42,8 @@ class Text: QueryComponent() { fun rBaseBuilder(): StringBuilder { val builder = StringBuilder() - for(component in components) { - when(component) { + for (component in components) { + when (component) { is StringTextComponent -> builder += escapeLike(component.value) is SingleWildcard -> builder += "_" is MultiWildcard -> builder += "%" @@ -52,7 +52,7 @@ class Text: QueryComponent() { return builder } - fun rawTextOnly() = if(rawText != null) + fun rawTextOnly() = if (rawText != null) rawText!! else { rawText = components diff --git a/app/src/main/java/exh/smartsearch/SmartSearchEngine.kt b/app/src/main/java/exh/smartsearch/SmartSearchEngine.kt index 111367912..1bc53bb64 100644 --- a/app/src/main/java/exh/smartsearch/SmartSearchEngine.kt +++ b/app/src/main/java/exh/smartsearch/SmartSearchEngine.kt @@ -8,13 +8,19 @@ import eu.kanade.tachiyomi.source.model.SManga import exh.ui.smartsearch.SmartSearchPresenter import exh.util.await import info.debatty.java.stringsimilarity.NormalizedLevenshtein -import kotlinx.coroutines.* +import kotlin.coroutines.CoroutineContext +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.async +import kotlinx.coroutines.supervisorScope import rx.schedulers.Schedulers import uy.kohesive.injekt.injectLazy -import kotlin.coroutines.CoroutineContext -class SmartSearchEngine(parentContext: CoroutineContext, - val extraSearchParams: String? = null): CoroutineScope { +class SmartSearchEngine( + parentContext: CoroutineContext, + val extraSearchParams: String? = null +) : CoroutineScope { override val coroutineContext: CoroutineContext = parentContext + Job() + Dispatchers.Default private val db: DatabaseHelper by injectLazy() @@ -29,7 +35,7 @@ class SmartSearchEngine(parentContext: CoroutineContext, val eligibleManga = supervisorScope { queries.map { query -> async(Dispatchers.Default) { - val builtQuery = if(extraSearchParams != null) { + val builtQuery = if (extraSearchParams != null) { "$query ${extraSearchParams.trim()}" } else query @@ -51,7 +57,7 @@ class SmartSearchEngine(parentContext: CoroutineContext, suspend fun normalSearch(source: CatalogueSource, title: String): SManga? { val eligibleManga = supervisorScope { - val searchQuery = if(extraSearchParams != null) { + val searchQuery = if (extraSearchParams != null) { "$title ${extraSearchParams.trim()}" } else title val searchResults = source.fetchSearchManga(1, searchQuery, FilterList()).toSingle().await(Schedulers.io()) @@ -71,7 +77,7 @@ class SmartSearchEngine(parentContext: CoroutineContext, val splitCleanedTitle = cleanedTitle.split(" ") val splitSortedByLargest = splitCleanedTitle.sortedByDescending { it.length } - if(splitCleanedTitle.isEmpty()) { + if (splitCleanedTitle.isEmpty()) { return emptyList() } @@ -99,7 +105,7 @@ class SmartSearchEngine(parentContext: CoroutineContext, // Remove text in brackets var cleanedTitle = removeTextInBrackets(preTitle, true) - if(cleanedTitle.length <= 5) { // Title is suspiciously short, try parsing it backwards + if (cleanedTitle.length <= 5) { // Title is suspiciously short, try parsing it backwards cleanedTitle = removeTextInBrackets(preTitle, false) } @@ -127,7 +133,7 @@ class SmartSearchEngine(parentContext: CoroutineContext, }.toMap() // Reverse pairs if reading backwards - if(!readForward) { + if (!readForward) { val tmp = openingBracketPairs openingBracketPairs = closingBracketPairs closingBracketPairs = tmp @@ -136,16 +142,16 @@ class SmartSearchEngine(parentContext: CoroutineContext, val depthPairs = bracketPairs.map { 0 }.toMutableList() val result = StringBuilder() - for(c in if(readForward) text else text.reversed()) { + for (c in if (readForward) text else text.reversed()) { val openingBracketDepthIndex = openingBracketPairs[c] - if(openingBracketDepthIndex != null) { + if (openingBracketDepthIndex != null) { depthPairs[openingBracketDepthIndex]++ } else { val closingBracketDepthIndex = closingBracketPairs[c] - if(closingBracketDepthIndex != null) { + if (closingBracketDepthIndex != null) { depthPairs[closingBracketDepthIndex]-- } else { - if(depthPairs.all { it <= 0 }) { + if (depthPairs.all { it <= 0 }) { result.append(c) } else { // In brackets, do not append to result @@ -183,4 +189,4 @@ class SmartSearchEngine(parentContext: CoroutineContext, private val titleRegex = Regex("[^a-zA-Z0-9- ]") private val consecutiveSpacesRegex = Regex(" +") } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/source/DelegatedHttpSource.kt b/app/src/main/java/exh/source/DelegatedHttpSource.kt index b5743537e..9213e1c17 100644 --- a/app/src/main/java/exh/source/DelegatedHttpSource.kt +++ b/app/src/main/java/exh/source/DelegatedHttpSource.kt @@ -1,29 +1,32 @@ package exh.source -import eu.kanade.tachiyomi.source.model.* +import eu.kanade.tachiyomi.source.model.FilterList +import eu.kanade.tachiyomi.source.model.MangasPage +import eu.kanade.tachiyomi.source.model.Page +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.online.HttpSource import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response import rx.Observable -import java.lang.RuntimeException -abstract class DelegatedHttpSource(val delegate: HttpSource): HttpSource() { +abstract class DelegatedHttpSource(val delegate: HttpSource) : HttpSource() { /** * Returns the request for the popular manga given the page. * * @param page the page number to retrieve. */ - override fun popularMangaRequest(page: Int) - = throw UnsupportedOperationException("Should never be called!") + override fun popularMangaRequest(page: Int) = + throw UnsupportedOperationException("Should never be called!") /** * Parses the response from the site and returns a [MangasPage] object. * * @param response the response from the site. */ - override fun popularMangaParse(response: Response) - = throw UnsupportedOperationException("Should never be called!") + override fun popularMangaParse(response: Response) = + throw UnsupportedOperationException("Should never be called!") /** * Returns the request for the search manga given the page. @@ -32,64 +35,64 @@ abstract class DelegatedHttpSource(val delegate: HttpSource): HttpSource() { * @param query the search query. * @param filters the list of filters to apply. */ - override fun searchMangaRequest(page: Int, query: String, filters: FilterList) - = throw UnsupportedOperationException("Should never be called!") + override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = + throw UnsupportedOperationException("Should never be called!") /** * Parses the response from the site and returns a [MangasPage] object. * * @param response the response from the site. */ - override fun searchMangaParse(response: Response) - = throw UnsupportedOperationException("Should never be called!") + override fun searchMangaParse(response: Response) = + throw UnsupportedOperationException("Should never be called!") /** * Returns the request for latest manga given the page. * * @param page the page number to retrieve. */ - override fun latestUpdatesRequest(page: Int) - = throw UnsupportedOperationException("Should never be called!") + override fun latestUpdatesRequest(page: Int) = + throw UnsupportedOperationException("Should never be called!") /** * Parses the response from the site and returns a [MangasPage] object. * * @param response the response from the site. */ - override fun latestUpdatesParse(response: Response) - = throw UnsupportedOperationException("Should never be called!") + override fun latestUpdatesParse(response: Response) = + throw UnsupportedOperationException("Should never be called!") /** * Parses the response from the site and returns the details of a manga. * * @param response the response from the site. */ - override fun mangaDetailsParse(response: Response) - = throw UnsupportedOperationException("Should never be called!") + override fun mangaDetailsParse(response: Response) = + throw UnsupportedOperationException("Should never be called!") /** * Parses the response from the site and returns a list of chapters. * * @param response the response from the site. */ - override fun chapterListParse(response: Response) - = throw UnsupportedOperationException("Should never be called!") + override fun chapterListParse(response: Response) = + throw UnsupportedOperationException("Should never be called!") /** * Parses the response from the site and returns a list of pages. * * @param response the response from the site. */ - override fun pageListParse(response: Response) - = throw UnsupportedOperationException("Should never be called!") + override fun pageListParse(response: Response) = + throw UnsupportedOperationException("Should never be called!") /** * Parses the response from the site and returns the absolute url to the source image. * * @param response the response from the site. */ - override fun imageUrlParse(response: Response) - = throw UnsupportedOperationException("Should never be called!") + override fun imageUrlParse(response: Response) = + throw UnsupportedOperationException("Should never be called!") /** * Base url of the website without the trailing slash, like: http://mysite.com @@ -236,8 +239,8 @@ abstract class DelegatedHttpSource(val delegate: HttpSource): HttpSource() { override fun getFilterList() = delegate.getFilterList() private fun ensureDelegateCompatible() { - if(versionId != delegate.versionId - || lang != delegate.lang) { + if (versionId != delegate.versionId || + lang != delegate.lang) { throw IncompatibleDelegateException("Delegate source is not compatible (versionId: $versionId <=> ${delegate.versionId}, lang: $lang <=> ${delegate.lang})!") } } @@ -247,4 +250,4 @@ abstract class DelegatedHttpSource(val delegate: HttpSource): HttpSource() { init { delegate.bindDelegate(this) } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/source/EnhancedHttpSource.kt b/app/src/main/java/exh/source/EnhancedHttpSource.kt index d556cba50..c7467acc3 100644 --- a/app/src/main/java/exh/source/EnhancedHttpSource.kt +++ b/app/src/main/java/exh/source/EnhancedHttpSource.kt @@ -2,13 +2,19 @@ package exh.source import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault -import eu.kanade.tachiyomi.source.model.* +import eu.kanade.tachiyomi.source.model.FilterList +import eu.kanade.tachiyomi.source.model.MangasPage +import eu.kanade.tachiyomi.source.model.Page +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.online.HttpSource import okhttp3.Response import uy.kohesive.injekt.injectLazy -class EnhancedHttpSource(val originalSource: HttpSource, - val enchancedSource: HttpSource): HttpSource() { +class EnhancedHttpSource( + val originalSource: HttpSource, + val enchancedSource: HttpSource +) : HttpSource() { private val prefs: PreferencesHelper by injectLazy() /** @@ -16,16 +22,16 @@ class EnhancedHttpSource(val originalSource: HttpSource, * * @param page the page number to retrieve. */ - override fun popularMangaRequest(page: Int) - = throw UnsupportedOperationException("Should never be called!") + override fun popularMangaRequest(page: Int) = + throw UnsupportedOperationException("Should never be called!") /** * Parses the response from the site and returns a [MangasPage] object. * * @param response the response from the site. */ - override fun popularMangaParse(response: Response) - = throw UnsupportedOperationException("Should never be called!") + override fun popularMangaParse(response: Response) = + throw UnsupportedOperationException("Should never be called!") /** * Returns the request for the search manga given the page. @@ -34,64 +40,64 @@ class EnhancedHttpSource(val originalSource: HttpSource, * @param query the search query. * @param filters the list of filters to apply. */ - override fun searchMangaRequest(page: Int, query: String, filters: FilterList) - = throw UnsupportedOperationException("Should never be called!") + override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = + throw UnsupportedOperationException("Should never be called!") /** * Parses the response from the site and returns a [MangasPage] object. * * @param response the response from the site. */ - override fun searchMangaParse(response: Response) - = throw UnsupportedOperationException("Should never be called!") + override fun searchMangaParse(response: Response) = + throw UnsupportedOperationException("Should never be called!") /** * Returns the request for latest manga given the page. * * @param page the page number to retrieve. */ - override fun latestUpdatesRequest(page: Int) - = throw UnsupportedOperationException("Should never be called!") + override fun latestUpdatesRequest(page: Int) = + throw UnsupportedOperationException("Should never be called!") /** * Parses the response from the site and returns a [MangasPage] object. * * @param response the response from the site. */ - override fun latestUpdatesParse(response: Response) - = throw UnsupportedOperationException("Should never be called!") + override fun latestUpdatesParse(response: Response) = + throw UnsupportedOperationException("Should never be called!") /** * Parses the response from the site and returns the details of a manga. * * @param response the response from the site. */ - override fun mangaDetailsParse(response: Response) - = throw UnsupportedOperationException("Should never be called!") + override fun mangaDetailsParse(response: Response) = + throw UnsupportedOperationException("Should never be called!") /** * Parses the response from the site and returns a list of chapters. * * @param response the response from the site. */ - override fun chapterListParse(response: Response) - = throw UnsupportedOperationException("Should never be called!") + override fun chapterListParse(response: Response) = + throw UnsupportedOperationException("Should never be called!") /** * Parses the response from the site and returns a list of pages. * * @param response the response from the site. */ - override fun pageListParse(response: Response) - = throw UnsupportedOperationException("Should never be called!") + override fun pageListParse(response: Response) = + throw UnsupportedOperationException("Should never be called!") /** * Parses the response from the site and returns the absolute url to the source image. * * @param response the response from the site. */ - override fun imageUrlParse(response: Response) - = throw UnsupportedOperationException("Should never be called!") + override fun imageUrlParse(response: Response) = + throw UnsupportedOperationException("Should never be called!") /** * Base url of the website without the trailing slash, like: http://mysite.com @@ -146,8 +152,8 @@ class EnhancedHttpSource(val originalSource: HttpSource, * @param query the search query. * @param filters the list of filters to apply. */ - override fun fetchSearchManga(page: Int, query: String, filters: FilterList) - = source().fetchSearchManga(page, query, filters) + override fun fetchSearchManga(page: Int, query: String, filters: FilterList) = + source().fetchSearchManga(page, query, filters) /** * Returns an observable containing a page with a list of latest manga updates. @@ -202,8 +208,8 @@ class EnhancedHttpSource(val originalSource: HttpSource, * @param chapter the chapter to be added. * @param manga the manga of the chapter. */ - override fun prepareNewChapter(chapter: SChapter, manga: SManga) - = source().prepareNewChapter(chapter, manga) + override fun prepareNewChapter(chapter: SChapter, manga: SManga) = + source().prepareNewChapter(chapter, manga) /** * Returns the list of filters for the source. @@ -211,10 +217,10 @@ class EnhancedHttpSource(val originalSource: HttpSource, override fun getFilterList() = source().getFilterList() private fun source(): HttpSource { - return if(prefs.eh_delegateSources().getOrDefault()) { + return if (prefs.eh_delegateSources().getOrDefault()) { enchancedSource } else { originalSource } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/uconfig/ConfiguringDialogController.kt b/app/src/main/java/exh/uconfig/ConfiguringDialogController.kt index ca580cbf1..61922b59b 100644 --- a/app/src/main/java/exh/uconfig/ConfiguringDialogController.kt +++ b/app/src/main/java/exh/uconfig/ConfiguringDialogController.kt @@ -7,14 +7,14 @@ import com.afollestad.materialdialogs.MaterialDialog import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.system.toast -import timber.log.Timber import kotlin.concurrent.thread +import timber.log.Timber class ConfiguringDialogController : DialogController() { private var materialDialog: MaterialDialog? = null override fun onCreateDialog(savedViewState: Bundle?): Dialog { - if(savedViewState == null) + if (savedViewState == null) thread { try { EHConfigurator().configureAll() @@ -62,4 +62,3 @@ class ConfiguringDialogController : DialogController() { router.popController(this) } } - diff --git a/app/src/main/java/exh/uconfig/EHConfigurator.kt b/app/src/main/java/exh/uconfig/EHConfigurator.kt index f6d60048a..d7794d705 100644 --- a/app/src/main/java/exh/uconfig/EHConfigurator.kt +++ b/app/src/main/java/exh/uconfig/EHConfigurator.kt @@ -24,11 +24,13 @@ class EHConfigurator { private fun EHentai.requestWithCreds(sp: Int = 1) = Request.Builder() .addHeader("Cookie", cookiesHeader(sp)) - private fun EHentai.execProfileActions(action: String, - name: String, - set: String, - sp: Int) - = configuratorClient.newCall(requestWithCreds(sp) + private fun EHentai.execProfileActions( + action: String, + name: String, + set: String, + sp: Int + ) = + configuratorClient.newCall(requestWithCreds(sp) .url(uconfigUrl) .post(FormBody.Builder() .add("profile_action", action) @@ -44,7 +46,7 @@ class EHConfigurator { val ehSource = sources.get(EH_SOURCE_ID) as EHentai val exhSource = sources.get(EXH_SOURCE_ID) as EHentai - //Get hath perks + // Get hath perks val perksPage = configuratorClient.newCall(ehSource.requestWithCreds() .url(HATH_PERKS_URL) .build()) @@ -56,13 +58,13 @@ class EHConfigurator { val name = it.child(0).text().toLowerCase() val purchased = it.child(2).getElementsByTag("form").isEmpty() - when(name) { - //Thumbnail rows + when (name) { + // Thumbnail rows "more thumbs" -> hathPerks.moreThumbs = purchased "thumbs up" -> hathPerks.thumbsUp = purchased "all thumbs" -> hathPerks.allThumbs = purchased - //Pagination sizing + // Pagination sizing "paging enlargement i" -> hathPerks.pagingEnlargementI = purchased "paging enlargement ii" -> hathPerks.pagingEnlargementII = purchased "paging enlargement iii" -> hathPerks.pagingEnlargementIII = purchased @@ -76,45 +78,45 @@ class EHConfigurator { } fun configure(source: EHentai, hathPerks: EHHathPerksResponse) { - //Delete old app profiles + // Delete old app profiles val scanReq = source.requestWithCreds().url(source.uconfigUrl).build() val resp = configuratorClient.newCall(scanReq).execute().asJsoup() var lastDoc = resp resp.select(PROFILE_SELECTOR).forEach { - if(it.text() == PROFILE_NAME) { + if (it.text() == PROFILE_NAME) { val id = it.attr("value") - //Delete old profile + // Delete old profile lastDoc = source.execProfileActions("delete", "", id, id.toInt()).asJsoup() } } - //Find available profile slot - val availableProfiles = (1 .. 3).toMutableList() + // Find available profile slot + val availableProfiles = (1..3).toMutableList() lastDoc.select(PROFILE_SELECTOR).forEach { availableProfiles.remove(it.attr("value").toInt()) } - //No profile slots left :( - if(availableProfiles.isEmpty()) + // No profile slots left :( + if (availableProfiles.isEmpty()) throw IllegalStateException("You are out of profile slots on ${source.name}, please delete a profile!") - //Create profile in available slot + // Create profile in available slot val slot = availableProfiles.first() val response = source.execProfileActions("create", PROFILE_NAME, slot.toString(), 1) - //Build new profile + // Build new profile val form = EhUConfigBuilder().build(hathPerks) - //Send new profile to server + // Send new profile to server configuratorClient.newCall(source.requestWithCreds(sp = slot) .url(source.uconfigUrl) .post(form) .build()).execute() - //Persist slot + sk + // Persist slot + sk source.spPref().set(slot) val keyCookie = response.headers.toMultimap()["Set-Cookie"]?.find { @@ -127,19 +129,19 @@ class EHConfigurator { it.startsWith("hath_perks=") }?.removePrefix("hath_perks=")?.substringBefore(';') - if(keyCookie != null) + if (keyCookie != null) prefs.eh_settingsKey().set(keyCookie) - if(sessionCookie != null) + if (sessionCookie != null) prefs.eh_sessionCookie().set(sessionCookie) - if(hathPerksCookie != null) + if (hathPerksCookie != null) prefs.eh_hathPerksCookies().set(hathPerksCookie) } companion object { private const val PROFILE_NAME = "TachiyomiEH App" private const val UCONFIG_URL = "/uconfig.php" - //Always use E-H here as EXH does not have a perks page + // Always use E-H here as EXH does not have a perks page private const val HATH_PERKS_URL = "https://e-hentai.org/hathperks.php" private const val PROFILE_SELECTOR = "[name=profile_set] > option" } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/uconfig/EHHathPerksResponse.kt b/app/src/main/java/exh/uconfig/EHHathPerksResponse.kt index ca5a23fe8..5d1f9f86f 100644 --- a/app/src/main/java/exh/uconfig/EHHathPerksResponse.kt +++ b/app/src/main/java/exh/uconfig/EHHathPerksResponse.kt @@ -9,7 +9,6 @@ class EHHathPerksResponse { var pagingEnlargementII = false var pagingEnlargementIII = false - override fun toString() - = "EHHathPerksResponse(moreThumbs=$moreThumbs, thumbsUp=$thumbsUp, allThumbs=$allThumbs, pagingEnlargementI=$pagingEnlargementI, pagingEnlargementII=$pagingEnlargementII, pagingEnlargementIII=$pagingEnlargementIII)" + override fun toString() = + "EHHathPerksResponse(moreThumbs=$moreThumbs, thumbsUp=$thumbsUp, allThumbs=$allThumbs, pagingEnlargementI=$pagingEnlargementI, pagingEnlargementII=$pagingEnlargementII, pagingEnlargementIII=$pagingEnlargementIII)" } - diff --git a/app/src/main/java/exh/uconfig/EhUConfigBuilder.kt b/app/src/main/java/exh/uconfig/EhUConfigBuilder.kt index 3f1f671a8..6c2567093 100644 --- a/app/src/main/java/exh/uconfig/EhUConfigBuilder.kt +++ b/app/src/main/java/exh/uconfig/EhUConfigBuilder.kt @@ -11,7 +11,7 @@ class EhUConfigBuilder { fun build(hathPerks: EHHathPerksResponse): FormBody { val configItems = mutableListOf() - configItems += when(prefs.imageQuality() + configItems += when (prefs.imageQuality() .getOrDefault() .toLowerCase()) { "ovrs_2400" -> Entry.ImageSize.`2400` @@ -23,17 +23,17 @@ class EhUConfigBuilder { else -> Entry.ImageSize.AUTO } - configItems += if(prefs.useHentaiAtHome().getOrDefault()) + configItems += if (prefs.useHentaiAtHome().getOrDefault()) Entry.UseHentaiAtHome.YES else Entry.UseHentaiAtHome.NO - configItems += if(prefs.useJapaneseTitle().getOrDefault()) + configItems += if (prefs.useJapaneseTitle().getOrDefault()) Entry.TitleDisplayLanguage.JAPANESE else Entry.TitleDisplayLanguage.DEFAULT - configItems += if(prefs.eh_useOriginalImages().getOrDefault()) + configItems += if (prefs.eh_useOriginalImages().getOrDefault()) Entry.UseOriginalImages.YES else Entry.UseOriginalImages.NO @@ -56,7 +56,7 @@ class EhUConfigBuilder { configItems += Entry.UseMPV() configItems += Entry.ShowPopularRightNowPane() - //Actually build form body + // Actually build form body val formBody = FormBody.Builder() configItems.forEach { formBody.add(it.key, it.value) @@ -67,14 +67,14 @@ class EhUConfigBuilder { } object Entry { - enum class UseHentaiAtHome(override val value: String): ConfigItem { + enum class UseHentaiAtHome(override val value: String) : ConfigItem { YES("0"), NO("1"); override val key = "uh" } - enum class ImageSize(override val value: String): ConfigItem { + enum class ImageSize(override val value: String) : ConfigItem { AUTO("0"), `2400`("5"), `1600`("4"), @@ -85,20 +85,20 @@ object Entry { override val key = "xr" } - enum class TitleDisplayLanguage(override val value: String): ConfigItem { + enum class TitleDisplayLanguage(override val value: String) : ConfigItem { DEFAULT("0"), JAPANESE("1"); override val key = "tl" } - //Locked to extended mode as that's what the parser and toplists use - class DisplayMode: ConfigItem { + // Locked to extended mode as that's what the parser and toplists use + class DisplayMode : ConfigItem { override val key = "dm" override val value = "2" } - enum class SearchResultsCount(override val value: String): ConfigItem { + enum class SearchResultsCount(override val value: String) : ConfigItem { `25`("0"), `50`("1"), `100`("2"), @@ -107,7 +107,7 @@ object Entry { override val key = "rc" } - enum class ThumbnailRows(override val value: String): ConfigItem { + enum class ThumbnailRows(override val value: String) : ConfigItem { `4`("0"), `10`("1"), `20`("2"), @@ -116,21 +116,21 @@ object Entry { override val key = "tr" } - enum class UseOriginalImages(override val value: String): ConfigItem { + enum class UseOriginalImages(override val value: String) : ConfigItem { NO("0"), YES("1"); override val key = "oi" } - //Locked to no MPV as that's what the parser uses - class UseMPV: ConfigItem { + // Locked to no MPV as that's what the parser uses + class UseMPV : ConfigItem { override val key = "qb" override val value = "0" } - //Locked to no popular pane as we can't parse it - class ShowPopularRightNowPane: ConfigItem { + // Locked to no popular pane as we can't parse it + class ShowPopularRightNowPane : ConfigItem { override val key = "pp" override val value = "1" } @@ -139,4 +139,4 @@ object Entry { interface ConfigItem { val key: String val value: String -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/uconfig/WarnConfigureDialogController.kt b/app/src/main/java/exh/uconfig/WarnConfigureDialogController.kt index c057cca8b..e50abd16a 100644 --- a/app/src/main/java/exh/uconfig/WarnConfigureDialogController.kt +++ b/app/src/main/java/exh/uconfig/WarnConfigureDialogController.kt @@ -32,10 +32,10 @@ class WarnConfigureDialogController : DialogController() { companion object { fun uploadSettings(router: Router) { - if(Injekt.get().eh_showSettingsUploadWarning().getOrDefault()) + if (Injekt.get().eh_showSettingsUploadWarning().getOrDefault()) WarnConfigureDialogController().showDialog(router) else ConfiguringDialogController().showDialog(router) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/ui/LoaderManager.kt b/app/src/main/java/exh/ui/LoaderManager.kt index 1d0f64221..f30318e19 100644 --- a/app/src/main/java/exh/ui/LoaderManager.kt +++ b/app/src/main/java/exh/ui/LoaderManager.kt @@ -1,18 +1,18 @@ package exh.ui +import java.util.UUID +import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.EmptyCoroutineContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import java.util.* -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext typealias LoadingHandle = String /** * Class used to manage loader UIs */ -class LoaderManager(parentContext: CoroutineContext = EmptyCoroutineContext): CoroutineScope { +class LoaderManager(parentContext: CoroutineContext = EmptyCoroutineContext) : CoroutineScope { override val coroutineContext = Dispatchers.Main + parentContext private val openLoadingHandles = mutableListOf() @@ -25,7 +25,7 @@ class LoaderManager(parentContext: CoroutineContext = EmptyCoroutineContext): Co handle to (openLoadingHandles.size == 1) } - if(shouldUpdateLoadingStatus) { + if (shouldUpdateLoadingStatus) { launch { updateLoadingStatus(true) } @@ -36,13 +36,13 @@ class LoaderManager(parentContext: CoroutineContext = EmptyCoroutineContext): Co @Synchronized fun closeProgressBar(handle: LoadingHandle?) { - if(handle == null) return + if (handle == null) return val shouldUpdateLoadingStatus = synchronized(this) { openLoadingHandles.remove(handle) && openLoadingHandles.isEmpty() } - if(shouldUpdateLoadingStatus) { + if (shouldUpdateLoadingStatus) { launch { updateLoadingStatus(false) } diff --git a/app/src/main/java/exh/ui/base/BaseExhController.kt b/app/src/main/java/exh/ui/base/BaseExhController.kt index d913e52a9..84181abe3 100644 --- a/app/src/main/java/exh/ui/base/BaseExhController.kt +++ b/app/src/main/java/exh/ui/base/BaseExhController.kt @@ -6,11 +6,11 @@ import android.view.View import android.view.ViewGroup import androidx.annotation.LayoutRes import eu.kanade.tachiyomi.ui.base.controller.BaseController +import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.cancel -import kotlin.coroutines.CoroutineContext abstract class BaseExhController(bundle: Bundle? = null) : BaseController(bundle), CoroutineScope { abstract val layoutId: Int diff --git a/app/src/main/java/exh/ui/batchadd/BatchAddController.kt b/app/src/main/java/exh/ui/batchadd/BatchAddController.kt index eda8e7f73..7bf51debe 100755 --- a/app/src/main/java/exh/ui/batchadd/BatchAddController.kt +++ b/app/src/main/java/exh/ui/batchadd/BatchAddController.kt @@ -1,6 +1,5 @@ package exh.ui.batchadd -import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -44,14 +43,14 @@ class BatchAddController : NucleusController() { .observeOn(AndroidSchedulers.mainThread()) .subscribeUntilDestroy { progressSubscriptions.clear() - if(it == BatchAddPresenter.STATE_INPUT_TO_PROGRESS) { + if (it == BatchAddPresenter.STATE_INPUT_TO_PROGRESS) { showProgress(this) progressSubscriptions += presenter.progressRelay .observeOn(AndroidSchedulers.mainThread()) .combineLatest(presenter.progressTotalRelay, { progress, total -> - //Show hide dismiss button + // Show hide dismiss button progress_dismiss_btn.visibility = - if(progress == total) + if (progress == total) View.VISIBLE else View.GONE @@ -79,7 +78,7 @@ class BatchAddController : NucleusController() { }?.let { progressSubscriptions += it } - } else if(it == BatchAddPresenter.STATE_PROGRESS_TO_INPUT) { + } else if (it == BatchAddPresenter.STATE_PROGRESS_TO_INPUT) { hideProgress(this) presenter.currentlyAddingRelay.call(BatchAddPresenter.STATE_IDLE) } @@ -124,8 +123,8 @@ class BatchAddController : NucleusController() { private fun formatProgress(progress: Int, total: Int) = "$progress/$total" private fun addGalleries(galleries: String) { - //Check text box has content - if(galleries.isBlank()) { + // Check text box has content + if (galleries.isBlank()) { noGalleriesSpecified() return } diff --git a/app/src/main/java/exh/ui/batchadd/BatchAddPresenter.kt b/app/src/main/java/exh/ui/batchadd/BatchAddPresenter.kt index a6216a626..241b143c0 100644 --- a/app/src/main/java/exh/ui/batchadd/BatchAddPresenter.kt +++ b/app/src/main/java/exh/ui/batchadd/BatchAddPresenter.kt @@ -8,7 +8,7 @@ import exh.GalleryAdder import exh.metadata.nullIfBlank import kotlin.concurrent.thread -class BatchAddPresenter: BasePresenter() { +class BatchAddPresenter : BasePresenter() { private val galleryAdder by lazy { GalleryAdder() } @@ -34,7 +34,7 @@ class BatchAddPresenter: BasePresenter() { splitGalleries.forEachIndexed { i, s -> val result = galleryAdder.addGallery(s, true) - if(result is GalleryAddEvent.Success) { + if (result is GalleryAddEvent.Success) { succeeded.add(s) } else { failed.add(s) @@ -46,7 +46,7 @@ class BatchAddPresenter: BasePresenter() { }) + " " + result.logMessage) } - //Show report + // Show report val summary = "\nSummary:\nAdded: ${succeeded.size} gallerie(s)\nFailed: ${failed.size} gallerie(s)" eventRelay?.call(summary) } diff --git a/app/src/main/java/exh/ui/captcha/AutoSolvingWebViewClient.kt b/app/src/main/java/exh/ui/captcha/AutoSolvingWebViewClient.kt index adda5df13..881d966fd 100644 --- a/app/src/main/java/exh/ui/captcha/AutoSolvingWebViewClient.kt +++ b/app/src/main/java/exh/ui/captcha/AutoSolvingWebViewClient.kt @@ -7,21 +7,23 @@ import android.webkit.WebView import androidx.annotation.RequiresApi import eu.kanade.tachiyomi.util.system.asJsoup import exh.ui.captcha.BrowserActionActivity.Companion.CROSS_WINDOW_SCRIPT_INNER +import java.nio.charset.Charset import org.jsoup.nodes.DataNode import org.jsoup.nodes.Element -import java.nio.charset.Charset @RequiresApi(Build.VERSION_CODES.LOLLIPOP) -class AutoSolvingWebViewClient(activity: BrowserActionActivity, - verifyComplete: (String) -> Boolean, - injectScript: String?, - headers: Map) - : HeadersInjectingWebViewClient(activity, verifyComplete, injectScript, headers) { +class AutoSolvingWebViewClient( + activity: BrowserActionActivity, + verifyComplete: (String) -> Boolean, + injectScript: String?, + headers: Map +) : + HeadersInjectingWebViewClient(activity, verifyComplete, injectScript, headers) { override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? { // Inject our custom script into the recaptcha iframes val lastPathSegment = request.url.pathSegments.lastOrNull() - if(lastPathSegment == "anchor" || lastPathSegment == "bframe") { + if (lastPathSegment == "anchor" || lastPathSegment == "bframe") { val oReq = request.toOkHttpRequest() val response = activity.httpClient.newCall(oReq).execute() val doc = response.asJsoup() @@ -34,4 +36,4 @@ class AutoSolvingWebViewClient(activity: BrowserActionActivity, } return super.shouldInterceptRequest(view, request) } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/ui/captcha/BasicWebViewClient.kt b/app/src/main/java/exh/ui/captcha/BasicWebViewClient.kt index b8dac1a63..7655834b4 100644 --- a/app/src/main/java/exh/ui/captcha/BasicWebViewClient.kt +++ b/app/src/main/java/exh/ui/captcha/BasicWebViewClient.kt @@ -4,17 +4,19 @@ import android.os.Build import android.webkit.WebView import android.webkit.WebViewClient -open class BasicWebViewClient(protected val activity: BrowserActionActivity, - protected val verifyComplete: (String) -> Boolean, - private val injectScript: String?) : WebViewClient() { +open class BasicWebViewClient( + protected val activity: BrowserActionActivity, + protected val verifyComplete: (String) -> Boolean, + private val injectScript: String? +) : WebViewClient() { override fun onPageFinished(view: WebView, url: String) { super.onPageFinished(view, url) - if(verifyComplete(url)) { + if (verifyComplete(url)) { activity.finish() } else { - if(injectScript != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) + if (injectScript != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) view.evaluateJavascript("(function() {$injectScript})();", null) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/ui/captcha/BrowserActionActivity.kt b/app/src/main/java/exh/ui/captcha/BrowserActionActivity.kt index 2ecd7a33c..42a08f37b 100644 --- a/app/src/main/java/exh/ui/captcha/BrowserActionActivity.kt +++ b/app/src/main/java/exh/ui/captcha/BrowserActionActivity.kt @@ -6,7 +6,12 @@ import android.os.Build import android.os.Bundle import android.os.SystemClock import android.view.MotionEvent -import android.webkit.* +import android.webkit.CookieManager +import android.webkit.CookieSyncManager +import android.webkit.JavascriptInterface +import android.webkit.JsResult +import android.webkit.WebChromeClient +import android.webkit.WebView import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity import com.afollestad.materialdialogs.MaterialDialog @@ -22,6 +27,9 @@ import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.online.HttpSource import exh.source.DelegatedHttpSource import exh.util.melt +import java.io.Serializable +import java.net.URL +import java.util.UUID import kotlinx.android.synthetic.main.eh_activity_captcha.* import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull @@ -33,10 +41,6 @@ import rx.Single import rx.schedulers.Schedulers import timber.log.Timber import uy.kohesive.injekt.injectLazy -import java.io.Serializable -import java.net.URL -import java.util.* -import kotlin.collections.HashMap class BrowserActionActivity : AppCompatActivity() { private val sourceManager: SourceManager by injectLazy() @@ -58,8 +62,8 @@ class BrowserActionActivity : AppCompatActivity() { setContentView(eu.kanade.tachiyomi.R.layout.eh_activity_captcha) val sourceId = intent.getLongExtra(SOURCE_ID_EXTRA, -1) - val originalSource = if(sourceId != -1L) sourceManager.get(sourceId) else null - val source = if(originalSource != null) { + val originalSource = if (sourceId != -1L) sourceManager.get(sourceId) else null + val source = if (originalSource != null) { originalSource as? ActionCompletionVerifier ?: run { (originalSource as? HttpSource)?.let { @@ -72,24 +76,24 @@ class BrowserActionActivity : AppCompatActivity() { it.value.joinToString(",") } ?: emptyMap()) + (intent.getSerializableExtra(HEADERS_EXTRA) as? HashMap ?: emptyMap()) - val cookies: HashMap? - = intent.getSerializableExtra(COOKIES_EXTRA) as? HashMap + val cookies: HashMap? = + intent.getSerializableExtra(COOKIES_EXTRA) as? HashMap val script: String? = intent.getStringExtra(SCRIPT_EXTRA) val url: String? = intent.getStringExtra(URL_EXTRA) val actionName = intent.getStringExtra(ACTION_NAME_EXTRA) - val verifyComplete = if(source != null) { + val verifyComplete = if (source != null) { source::verifyComplete!! } else intent.getSerializableExtra(VERIFY_LAMBDA_EXTRA) as? (String) -> Boolean - if(verifyComplete == null || url == null) { + if (verifyComplete == null || url == null) { finish() return } val actionStr = actionName ?: "Solve captcha" - toolbar.title = if(source != null) { + toolbar.title = if (source != null) { "${source.name}: $actionStr" } else actionStr @@ -115,13 +119,13 @@ class BrowserActionActivity : AppCompatActivity() { webview.webChromeClient = object : WebChromeClient() { override fun onJsAlert(view: WebView?, url: String?, message: String, result: JsResult): Boolean { - if(message.startsWith("exh-")) { + if (message.startsWith("exh-")) { loadedInners++ // Wait for both inner scripts to be loaded - if(loadedInners >= 2) { + if (loadedInners >= 2) { // Attempt to autosolve captcha - if(preferencesHelper.eh_autoSolveCaptchas().getOrDefault() - && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + if (preferencesHelper.eh_autoSolveCaptchas().getOrDefault() && + Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { webview.post { // 10 seconds to auto-solve captcha strictValidationStartTime = System.currentTimeMillis() + 1000 * 10 @@ -141,7 +145,7 @@ class BrowserActionActivity : AppCompatActivity() { } webview.webViewClient = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - if(actionName == null && preferencesHelper.eh_autoSolveCaptchas().getOrDefault()) { + if (actionName == null && preferencesHelper.eh_autoSolveCaptchas().getOrDefault()) { // Fetch auto-solve credentials early for speed credentialsObservable = httpClient.newCall(Request.Builder() // Rob demo credentials @@ -196,11 +200,11 @@ class BrowserActionActivity : AppCompatActivity() { @RequiresApi(Build.VERSION_CODES.LOLLIPOP) @JavascriptInterface fun callback(result: String?, loopId: String, stage: Int) { - if(loopId != currentLoopId) return + if (loopId != currentLoopId) return - when(stage) { + when (stage) { STAGE_CHECKBOX -> { - if(result!!.toBoolean()) { + if (result!!.toBoolean()) { webview.postDelayed({ getAudioButtonLocation(loopId) }, 250) @@ -211,7 +215,7 @@ class BrowserActionActivity : AppCompatActivity() { } } STAGE_GET_AUDIO_BTN_LOCATION -> { - if(result != null) { + if (result != null) { val splitResult = result.split(" ").map { it.toFloat() } val origX = splitResult[0] val origY = splitResult[1] @@ -231,11 +235,11 @@ class BrowserActionActivity : AppCompatActivity() { } } STAGE_DOWNLOAD_AUDIO -> { - if(result != null) { + if (result != null) { Timber.d("Got audio URL: $result") performRecognize(result) .observeOn(Schedulers.io()) - .subscribe ({ + .subscribe({ Timber.d("Got audio transcript: $it") webview.post { typeResult(loopId, it!! @@ -253,7 +257,7 @@ class BrowserActionActivity : AppCompatActivity() { } } STAGE_TYPE_RESULT -> { - if(result!!.toBoolean()) { + if (result!!.toBoolean()) { // Fail if captcha still not solved after 1.5s strictValidationStartTime = System.currentTimeMillis() + 1500 } else { @@ -293,7 +297,7 @@ class BrowserActionActivity : AppCompatActivity() { @RequiresApi(Build.VERSION_CODES.LOLLIPOP) fun doStageCheckbox(loopId: String) { - if(loopId != currentLoopId) return + if (loopId != currentLoopId) return webview.evaluateJavascript(""" (function() { @@ -415,27 +419,26 @@ class BrowserActionActivity : AppCompatActivity() { doStageCheckbox(loopId) } - @RequiresApi(Build.VERSION_CODES.LOLLIPOP) @JavascriptInterface fun validateCaptchaCallback(result: Boolean, loopId: String) { - if(loopId != validateCurrentLoopId) return + if (loopId != validateCurrentLoopId) return - if(result) { + if (result) { Timber.d("Captcha solved!") webview.post { webview.evaluateJavascript(SOLVE_UI_SCRIPT_HIDE, null) } val asbtn = intent.getStringExtra(ASBTN_EXTRA) - if(asbtn != null) { + if (asbtn != null) { webview.post { webview.evaluateJavascript("(function() {document.querySelector('$asbtn').click();})();", null) } } } else { val savedStrictValidationStartTime = strictValidationStartTime - if(savedStrictValidationStartTime != null - && System.currentTimeMillis() > savedStrictValidationStartTime) { + if (savedStrictValidationStartTime != null && + System.currentTimeMillis() > savedStrictValidationStartTime) { captchaSolveFail() } else { webview.postDelayed({ @@ -447,7 +450,7 @@ class BrowserActionActivity : AppCompatActivity() { @RequiresApi(Build.VERSION_CODES.LOLLIPOP) fun runValidateCaptcha(loopId: String) { - if(loopId != validateCurrentLoopId) return + if (loopId != validateCurrentLoopId) return webview.evaluateJavascript(""" (function() { @@ -624,12 +627,14 @@ class BrowserActionActivity : AppCompatActivity() { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) } - fun launchCaptcha(context: Context, - source: ActionCompletionVerifier, - cookies: Map, - script: String?, - url: String, - autoSolveSubmitBtnSelector: String? = null) { + fun launchCaptcha( + context: Context, + source: ActionCompletionVerifier, + cookies: Map, + script: String?, + url: String, + autoSolveSubmitBtnSelector: String? = null + ) { val intent = baseIntent(context).apply { putExtra(SOURCE_ID_EXTRA, source.id) putExtra(COOKIES_EXTRA, HashMap(cookies)) @@ -641,9 +646,11 @@ class BrowserActionActivity : AppCompatActivity() { context.startActivity(intent) } - fun launchUniversal(context: Context, - source: HttpSource, - url: String) { + fun launchUniversal( + context: Context, + source: HttpSource, + url: String + ) { val intent = baseIntent(context).apply { putExtra(SOURCE_ID_EXTRA, source.id) putExtra(URL_EXTRA, url) @@ -652,9 +659,11 @@ class BrowserActionActivity : AppCompatActivity() { context.startActivity(intent) } - fun launchUniversal(context: Context, - sourceId: Long, - url: String) { + fun launchUniversal( + context: Context, + sourceId: Long, + url: String + ) { val intent = baseIntent(context).apply { putExtra(SOURCE_ID_EXTRA, sourceId) putExtra(URL_EXTRA, url) @@ -663,11 +672,13 @@ class BrowserActionActivity : AppCompatActivity() { context.startActivity(intent) } - fun launchAction(context: Context, - completionVerifier: ActionCompletionVerifier, - script: String?, - url: String, - actionName: String) { + fun launchAction( + context: Context, + completionVerifier: ActionCompletionVerifier, + script: String?, + url: String, + actionName: String + ) { val intent = baseIntent(context).apply { putExtra(SOURCE_ID_EXTRA, completionVerifier.id) putExtra(SCRIPT_EXTRA, script) @@ -678,12 +689,14 @@ class BrowserActionActivity : AppCompatActivity() { context.startActivity(intent) } - fun launchAction(context: Context, - completionVerifier: (String) -> Boolean, - script: String?, - url: String, - actionName: String, - headers: Map? = emptyMap()) { + fun launchAction( + context: Context, + completionVerifier: (String) -> Boolean, + script: String?, + url: String, + actionName: String, + headers: Map? = emptyMap() + ) { val intent = baseIntent(context).apply { putExtra(HEADERS_EXTRA, HashMap(headers)) putExtra(VERIFY_LAMBDA_EXTRA, completionVerifier as Serializable) @@ -697,7 +710,7 @@ class BrowserActionActivity : AppCompatActivity() { } } -class NoopActionCompletionVerifier(private val source: HttpSource): DelegatedHttpSource(source), +class NoopActionCompletionVerifier(private val source: HttpSource) : DelegatedHttpSource(source), ActionCompletionVerifier { override val versionId get() = source.versionId override val lang: String get() = source.lang @@ -708,4 +721,3 @@ class NoopActionCompletionVerifier(private val source: HttpSource): DelegatedHtt interface ActionCompletionVerifier : Source { fun verifyComplete(url: String): Boolean } - diff --git a/app/src/main/java/exh/ui/captcha/HeadersInjectingWebViewClient.kt b/app/src/main/java/exh/ui/captcha/HeadersInjectingWebViewClient.kt index 2405bbd2d..1f01a66b2 100644 --- a/app/src/main/java/exh/ui/captcha/HeadersInjectingWebViewClient.kt +++ b/app/src/main/java/exh/ui/captcha/HeadersInjectingWebViewClient.kt @@ -7,11 +7,13 @@ import android.webkit.WebView import androidx.annotation.RequiresApi @RequiresApi(Build.VERSION_CODES.LOLLIPOP) -open class HeadersInjectingWebViewClient(activity: BrowserActionActivity, - verifyComplete: (String) -> Boolean, - injectScript: String?, - private val headers: Map) - : BasicWebViewClient(activity, verifyComplete, injectScript) { +open class HeadersInjectingWebViewClient( + activity: BrowserActionActivity, + verifyComplete: (String) -> Boolean, + injectScript: String?, + private val headers: Map +) : + BasicWebViewClient(activity, verifyComplete, injectScript) { override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? { // Temp disabled as it's unreliable diff --git a/app/src/main/java/exh/ui/captcha/WebViewUtil.kt b/app/src/main/java/exh/ui/captcha/WebViewUtil.kt index 6802bccd7..c89432bdf 100644 --- a/app/src/main/java/exh/ui/captcha/WebViewUtil.kt +++ b/app/src/main/java/exh/ui/captcha/WebViewUtil.kt @@ -16,4 +16,4 @@ fun WebResourceRequest.toOkHttpRequest(): Request { } return request.build() -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/ui/intercept/InterceptActivity.kt b/app/src/main/java/exh/ui/intercept/InterceptActivity.kt index 1e6cd64d0..231ed2080 100755 --- a/app/src/main/java/exh/ui/intercept/InterceptActivity.kt +++ b/app/src/main/java/exh/ui/intercept/InterceptActivity.kt @@ -23,7 +23,7 @@ class InterceptActivity : BaseRxActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.eh_activity_intercept) - //Show back button + // Show back button setSupportActionBar(toolbar) supportActionBar?.setDisplayHomeAsUpEnabled(true) @@ -31,7 +31,7 @@ class InterceptActivity : BaseRxActivity() { } private fun processLink() { - if(Intent.ACTION_VIEW == intent.action) { + if (Intent.ACTION_VIEW == intent.action) { intercept_progress.visible() intercept_status.text = "Loading gallery..." presenter.loadGallery(intent.dataString) @@ -52,7 +52,7 @@ class InterceptActivity : BaseRxActivity() { statusSubscription = presenter.status .observeOn(AndroidSchedulers.mainThread()) .subscribe { - when(it) { + when (it) { is InterceptResult.Success -> { intercept_progress.gone() intercept_status.text = "Launching app..." diff --git a/app/src/main/java/exh/ui/intercept/InterceptActivityPresenter.kt b/app/src/main/java/exh/ui/intercept/InterceptActivityPresenter.kt index 89c4c64b7..d69d0cc9d 100644 --- a/app/src/main/java/exh/ui/intercept/InterceptActivityPresenter.kt +++ b/app/src/main/java/exh/ui/intercept/InterceptActivityPresenter.kt @@ -3,8 +3,8 @@ package exh.ui.intercept import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import exh.GalleryAddEvent import exh.GalleryAdder -import rx.subjects.BehaviorSubject import kotlin.concurrent.thread +import rx.subjects.BehaviorSubject class InterceptActivityPresenter : BasePresenter() { private val galleryAdder = GalleryAdder() @@ -13,11 +13,11 @@ class InterceptActivityPresenter : BasePresenter() { @Synchronized fun loadGallery(gallery: String) { - //Do not load gallery if already loading - if(status.value is InterceptResult.Idle) { + // Do not load gallery if already loading + if (status.value is InterceptResult.Idle) { status.onNext(InterceptResult.Loading()) - //Load gallery async + // Load gallery async thread { val result = galleryAdder.addGallery(gallery) @@ -35,6 +35,6 @@ class InterceptActivityPresenter : BasePresenter() { sealed class InterceptResult { class Idle : InterceptResult() class Loading : InterceptResult() - data class Success(val mangaId: Long): InterceptResult() - data class Failure(val reason: String): InterceptResult() -} \ No newline at end of file + data class Success(val mangaId: Long) : InterceptResult() + data class Failure(val reason: String) : InterceptResult() +} diff --git a/app/src/main/java/exh/ui/lock/FingerLockPreference.kt b/app/src/main/java/exh/ui/lock/FingerLockPreference.kt index a87ab7a96..6abba875b 100644 --- a/app/src/main/java/exh/ui/lock/FingerLockPreference.kt +++ b/app/src/main/java/exh/ui/lock/FingerLockPreference.kt @@ -28,21 +28,21 @@ class FingerLockPreference @JvmOverloads constructor(context: Context, attrs: At val prefs: PreferencesHelper by injectLazy() val fingerprintSupported - get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M - && Reprint.isHardwarePresent() - && Reprint.hasFingerprintRegistered() + get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && + Reprint.isHardwarePresent() && + Reprint.hasFingerprintRegistered() val useFingerprint - get() = fingerprintSupported - && prefs.eh_lockUseFingerprint().getOrDefault() + get() = fingerprintSupported && + prefs.eh_lockUseFingerprint().getOrDefault() @SuppressLint("NewApi") override fun onAttached() { super.onAttached() - if(fingerprintSupported) { + if (fingerprintSupported) { updateSummary() onChange { - if(it as Boolean) + if (it as Boolean) tryChange() else prefs.eh_lockUseFingerprint().set(false) @@ -51,7 +51,7 @@ class FingerLockPreference @JvmOverloads constructor(context: Context, attrs: At } else { title = "Fingerprint unsupported" shouldDisableView = true - summary = if(!Reprint.hasFingerprintRegistered()) + summary = if (!Reprint.hasFingerprintRegistered()) "No fingerprints enrolled!" else "Fingerprint unlock is unsupported on this device!" @@ -61,7 +61,7 @@ class FingerLockPreference @JvmOverloads constructor(context: Context, attrs: At private fun updateSummary() { isChecked = useFingerprint - title = if(isChecked) + title = if (isChecked) "Fingerprint enabled" else "Fingerprint disabled" @@ -146,4 +146,4 @@ class FingerLockPreference @JvmOverloads constructor(context: Context, attrs: At subscription.unsubscribe() } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/ui/lock/LockActivityDelegate.kt b/app/src/main/java/exh/ui/lock/LockActivityDelegate.kt index 0ba5e40b4..67ce4243f 100644 --- a/app/src/main/java/exh/ui/lock/LockActivityDelegate.kt +++ b/app/src/main/java/exh/ui/lock/LockActivityDelegate.kt @@ -1,6 +1,5 @@ package exh.ui.lock -import android.content.Intent import android.view.WindowManager import androidx.fragment.app.FragmentActivity import com.bluelinelabs.conductor.Router @@ -8,7 +7,6 @@ import com.bluelinelabs.conductor.RouterTransaction import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault import uy.kohesive.injekt.injectLazy -import java.util.Date object LockActivityDelegate { private val preferences by injectLazy() @@ -20,7 +18,6 @@ object LockActivityDelegate { .popChangeHandler(LockChangeHandler(animate))) } - fun onCreate(activity: FragmentActivity) { preferences.secureScreen().asObservable() .subscribe { @@ -42,5 +39,4 @@ object LockActivityDelegate { private fun isAppLocked(router: Router): Boolean { return router.backstack.lastOrNull()?.controller() is LockController } - } diff --git a/app/src/main/java/exh/ui/lock/LockChangeHandler.kt b/app/src/main/java/exh/ui/lock/LockChangeHandler.kt index ae6750aef..e508165a6 100644 --- a/app/src/main/java/exh/ui/lock/LockChangeHandler.kt +++ b/app/src/main/java/exh/ui/lock/LockChangeHandler.kt @@ -7,10 +7,10 @@ import android.view.View import android.view.ViewGroup import com.bluelinelabs.conductor.ControllerChangeHandler import com.bluelinelabs.conductor.changehandler.AnimatorChangeHandler -import java.util.* +import java.util.ArrayList class LockChangeHandler : AnimatorChangeHandler { - constructor(): super() + constructor() : super() constructor(removesFromViewOnPush: Boolean) : super(removesFromViewOnPush) @@ -36,6 +36,4 @@ class LockChangeHandler : AnimatorChangeHandler { override fun copy(): ControllerChangeHandler = LockChangeHandler(animationDuration, removesFromViewOnPush()) - } - diff --git a/app/src/main/java/exh/ui/lock/LockController.kt b/app/src/main/java/exh/ui/lock/LockController.kt index 463c0085c..99d24afae 100755 --- a/app/src/main/java/exh/ui/lock/LockController.kt +++ b/app/src/main/java/exh/ui/lock/LockController.kt @@ -22,8 +22,8 @@ class LockController : NucleusController() { val prefs: PreferencesHelper by injectLazy() - override fun inflateView(inflater: LayoutInflater, container: ViewGroup) - = inflater.inflate(R.layout.activity_lock, container, false)!! + override fun inflateView(inflater: LayoutInflater, container: ViewGroup) = + inflater.inflate(R.layout.activity_lock, container, false)!! override fun createPresenter() = LockPresenter() @@ -32,13 +32,13 @@ class LockController : NucleusController() { override fun onViewCreated(view: View) { super.onViewCreated(view) - if(!lockEnabled(prefs)) { + if (!lockEnabled(prefs)) { closeLock() return } with(view) { - //Setup pin lock + // Setup pin lock pin_lock_view.attachIndicatorDots(indicator_dots) pin_lock_view.pinLength = prefs.eh_lockLength().getOrDefault() @@ -47,7 +47,7 @@ class LockController : NucleusController() { override fun onComplete(pin: String) { if (sha512(pin, prefs.eh_lockSalt().get()!!) == prefs.eh_lockHash().get()) { - //Yay! + // Yay! closeLock() } else { MaterialDialog.Builder(context) @@ -72,7 +72,7 @@ class LockController : NucleusController() { super.onAttach(view) with(view) { - //Fingerprint + // Fingerprint if (presenter.useFingerprint) { swirl_container.visibility = View.VISIBLE swirl_container.removeAllViews() @@ -90,7 +90,7 @@ class LockController : NucleusController() { val lockColor = resolvColor(android.R.attr.windowBackground) setBackgroundColor(lockColor) val bgColor = resolvColor(android.R.attr.colorBackground) - //Disable elevation if lock color is same as background color + // Disable elevation if lock color is same as background color if (lockColor == bgColor) this@with.swirl_container.cardElevation = 0f setState(SwirlView.State.OFF, true) diff --git a/app/src/main/java/exh/ui/lock/LockPreference.kt b/app/src/main/java/exh/ui/lock/LockPreference.kt index b87f4be07..b75562093 100755 --- a/app/src/main/java/exh/ui/lock/LockPreference.kt +++ b/app/src/main/java/exh/ui/lock/LockPreference.kt @@ -8,12 +8,12 @@ import com.afollestad.materialdialogs.MaterialDialog import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.util.preference.onChange +import java.math.BigInteger +import java.security.SecureRandom import rx.Observable import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers import uy.kohesive.injekt.injectLazy -import java.math.BigInteger -import java.security.SecureRandom class LockPreference @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : SwitchPreferenceCompat(context, attrs) { @@ -33,7 +33,7 @@ class LockPreference @JvmOverloads constructor(context: Context, attrs: Attribut private fun updateSummary() { isChecked = lockEnabled(prefs) - if(isChecked) { + if (isChecked) { title = "Lock enabled" summary = "Tap to disable or change pin code" } else { @@ -43,7 +43,7 @@ class LockPreference @JvmOverloads constructor(context: Context, attrs: Attribut } fun tryChange() { - if(!notifyLockSecurity(context)) { + if (!notifyLockSecurity(context)) { MaterialDialog.Builder(context) .title("Lock application") .content("Enter a pin to lock the application. Enter nothing to disable the pin lock.") @@ -76,7 +76,7 @@ class LockPreference @JvmOverloads constructor(context: Context, attrs: Attribut val salt: String? val hash: String? val length: Int - if(password.isEmpty()) { + if (password.isEmpty()) { salt = null hash = null length = -1 diff --git a/app/src/main/java/exh/ui/lock/LockPresenter.kt b/app/src/main/java/exh/ui/lock/LockPresenter.kt index 3bdc532f7..181cb959e 100644 --- a/app/src/main/java/exh/ui/lock/LockPresenter.kt +++ b/app/src/main/java/exh/ui/lock/LockPresenter.kt @@ -7,13 +7,12 @@ import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import uy.kohesive.injekt.injectLazy -class LockPresenter: BasePresenter() { +class LockPresenter : BasePresenter() { val prefs: PreferencesHelper by injectLazy() val useFingerprint - get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M - && Reprint.isHardwarePresent() - && Reprint.hasFingerprintRegistered() - && prefs.eh_lockUseFingerprint().getOrDefault() + get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && + Reprint.isHardwarePresent() && + Reprint.hasFingerprintRegistered() && + prefs.eh_lockUseFingerprint().getOrDefault() } - diff --git a/app/src/main/java/exh/ui/lock/LockUtils.kt b/app/src/main/java/exh/ui/lock/LockUtils.kt index f568567a1..c8f3f419f 100755 --- a/app/src/main/java/exh/ui/lock/LockUtils.kt +++ b/app/src/main/java/exh/ui/lock/LockUtils.kt @@ -13,11 +13,10 @@ import com.elvishew.xlog.XLog import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get import java.security.MessageDigest import kotlin.experimental.and - +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get /** * Password hashing utils @@ -40,22 +39,24 @@ fun sha512(passwordToHash: String, salt: String): String { /** * Check if lock is enabled */ -fun lockEnabled(prefs: PreferencesHelper = Injekt.get()) - = prefs.eh_lockHash().get() != null - && prefs.eh_lockSalt().get() != null - && prefs.eh_lockLength().getOrDefault() != -1 +fun lockEnabled(prefs: PreferencesHelper = Injekt.get()) = + prefs.eh_lockHash().get() != null && + prefs.eh_lockSalt().get() != null && + prefs.eh_lockLength().getOrDefault() != -1 /** * Check if the lock will function properly * * @return true if action is required, false if lock is working properly */ -fun notifyLockSecurity(context: Context, - prefs: PreferencesHelper = Injekt.get()): Boolean { +fun notifyLockSecurity( + context: Context, + prefs: PreferencesHelper = Injekt.get() +): Boolean { return false - if (!prefs.eh_lockManually().getOrDefault() - && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP - && !hasAccessToUsageStats(context)) { + if (!prefs.eh_lockManually().getOrDefault() && + Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && + !hasAccessToUsageStats(context)) { MaterialDialog.Builder(context) .title("Permission required") .content("${context.getString(R.string.app_name)} requires the usage stats permission to detect when you leave the app. " + @@ -66,7 +67,7 @@ fun notifyLockSecurity(context: Context, .onPositive { _, _ -> try { context.startActivity(Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)) - } catch(e: ActivityNotFoundException) { + } catch (e: ActivityNotFoundException) { XLog.e("Device does not support USAGE_ACCESS_SETTINGS shortcut!") MaterialDialog.Builder(context) .title("Grant permission manually") diff --git a/app/src/main/java/exh/ui/login/LoginController.kt b/app/src/main/java/exh/ui/login/LoginController.kt index 84517675d..8bb5482f1 100755 --- a/app/src/main/java/exh/ui/login/LoginController.kt +++ b/app/src/main/java/exh/ui/login/LoginController.kt @@ -12,14 +12,14 @@ import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.ui.base.controller.NucleusController -import eu.kanade.tachiyomi.util.view.gone import eu.kanade.tachiyomi.util.lang.launchUI +import eu.kanade.tachiyomi.util.view.gone import eu.kanade.tachiyomi.util.view.visible import exh.uconfig.WarnConfigureDialogController +import java.net.HttpCookie import kotlinx.android.synthetic.main.eh_activity_login.view.* import timber.log.Timber import uy.kohesive.injekt.injectLazy -import java.net.HttpCookie /** * LoginController @@ -104,17 +104,17 @@ class LoginController : NucleusController() { Timber.d(url) val parsedUrl = Uri.parse(url) if (parsedUrl.host.equals("forums.e-hentai.org", ignoreCase = true)) { - //Hide distracting content - if(!parsedUrl.queryParameterNames.contains(PARAM_SKIP_INJECT) - && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) + // Hide distracting content + if (!parsedUrl.queryParameterNames.contains(PARAM_SKIP_INJECT) && + Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) view.evaluateJavascript(HIDE_JS, null) - //Check login result + // Check login result if (parsedUrl.getQueryParameter("code")?.toInt() != 0) { if (checkLoginCookies(url)) view.loadUrl("https://exhentai.org/") } } else if (parsedUrl.host.equals("exhentai.org", ignoreCase = true)) { - //At ExHentai, check that everything worked out... + // At ExHentai, check that everything worked out... if (applyExHentaiCookies(url)) { preferenceManager.enableExhentai().set(true) finishLogin() @@ -128,7 +128,7 @@ class LoginController : NucleusController() { fun finishLogin() { router.popCurrentController() - //Upload settings + // Upload settings WarnConfigureDialogController.uploadSettings(router) } @@ -138,9 +138,9 @@ class LoginController : NucleusController() { fun checkLoginCookies(url: String): Boolean { getCookies(url)?.let { parsed -> return parsed.filter { - (it.name.equals(MEMBER_ID_COOKIE, ignoreCase = true) - || it.name.equals(PASS_HASH_COOKIE, ignoreCase = true)) - && it.value.isNotBlank() + (it.name.equals(MEMBER_ID_COOKIE, ignoreCase = true) || + it.name.equals(PASS_HASH_COOKIE, ignoreCase = true)) && + it.value.isNotBlank() }.count() >= 2 } return false @@ -164,10 +164,10 @@ class LoginController : NucleusController() { } } - //Missing a cookie + // Missing a cookie if (memberId == null || passHash == null || igneous == null) return false - //Update prefs + // Update prefs preferenceManager.memberIdVal().set(memberId) preferenceManager.passHashVal().set(passHash) preferenceManager.igneousVal().set(igneous) @@ -177,8 +177,8 @@ class LoginController : NucleusController() { return false } - fun getCookies(url: String): List? - = CookieManager.getInstance().getCookie(url)?.let { + fun getCookies(url: String): List? = + CookieManager.getInstance().getCookie(url)?.let { it.split("; ").flatMap { HttpCookie.parse(it) } diff --git a/app/src/main/java/exh/ui/login/LoginPresenter.kt b/app/src/main/java/exh/ui/login/LoginPresenter.kt index 3d39afcc5..6966341c7 100644 --- a/app/src/main/java/exh/ui/login/LoginPresenter.kt +++ b/app/src/main/java/exh/ui/login/LoginPresenter.kt @@ -2,6 +2,4 @@ package exh.ui.login import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter -class LoginPresenter: BasePresenter() { - -} \ No newline at end of file +class LoginPresenter : BasePresenter() diff --git a/app/src/main/java/exh/ui/migration/MetadataFetchDialog.kt b/app/src/main/java/exh/ui/migration/MetadataFetchDialog.kt index 8b9a8e6ab..575df854d 100755 --- a/app/src/main/java/exh/ui/migration/MetadataFetchDialog.kt +++ b/app/src/main/java/exh/ui/migration/MetadataFetchDialog.kt @@ -12,9 +12,9 @@ import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.source.SourceManager import exh.EXH_SOURCE_ID import exh.isLewdSource +import kotlin.concurrent.thread import timber.log.Timber import uy.kohesive.injekt.injectLazy -import kotlin.concurrent.thread class MetadataFetchDialog { @@ -25,7 +25,7 @@ class MetadataFetchDialog { val preferenceHelper: PreferencesHelper by injectLazy() fun show(context: Activity) { - //Too lazy to actually deal with orientation changes + // Too lazy to actually deal with orientation changes context.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR var running = true @@ -55,7 +55,7 @@ class MetadataFetchDialog { val mangaWithMissingMetadata = libraryMangas .filterIndexed { index, libraryManga -> - if(index % 100 == 0) { + if (index % 100 == 0) { context.runOnUiThread { progressDialog.setContent("[Stage 1/2] Scanning for missing metadata...") progressDialog.setProgress(index + 1) @@ -69,9 +69,9 @@ class MetadataFetchDialog { progressDialog.maxProgress = mangaWithMissingMetadata.size } - //Actual metadata fetch code - for((i, manga) in mangaWithMissingMetadata.withIndex()) { - if(!running) break + // Actual metadata fetch code + for ((i, manga) in mangaWithMissingMetadata.withIndex()) { + if (!running) break context.runOnUiThread { progressDialog.setContent("[Stage 2/2] Processing: ${manga.title}") progressDialog.setProgress(i + 1) @@ -88,10 +88,10 @@ class MetadataFetchDialog { context.runOnUiThread { // Ensure activity still exists before we do anything to the activity - if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1 || !context.isDestroyed) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1 || !context.isDestroyed) { progressDialog.dismiss() - //Enable orientation changes again + // Enable orientation changes again context.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR if (running) displayMigrationComplete(context) @@ -103,12 +103,12 @@ class MetadataFetchDialog { fun askMigration(activity: Activity, explicit: Boolean) { var extra = "" db.getLibraryMangas().asRxSingle().subscribe { - if(!explicit && it.none { isLewdSource(it.source) }) { + if (!explicit && it.none { isLewdSource(it.source) }) { // Do not open dialog on startup if no manga // Also do not check again preferenceHelper.migrateLibraryAsked().set(true) } else { - //Not logged in but have ExHentai galleries + // Not logged in but have ExHentai galleries if (!preferenceHelper.enableExhentai().getOrDefault()) { it.find { it.source == EXH_SOURCE_ID }?.let { extra = "If you use ExHentai, please log in first before fetching your library metadata!

" @@ -132,7 +132,6 @@ class MetadataFetchDialog { } } } - } fun adviseMigrationLater(activity: Activity) { diff --git a/app/src/main/java/exh/ui/migration/MigrationStatus.kt b/app/src/main/java/exh/ui/migration/MigrationStatus.kt index 1fa3aa5cf..333d85c92 100755 --- a/app/src/main/java/exh/ui/migration/MigrationStatus.kt +++ b/app/src/main/java/exh/ui/migration/MigrationStatus.kt @@ -5,7 +5,7 @@ class MigrationStatus { val NOT_INITIALIZED = -1 val COMPLETED = 0 - //Migration process + // Migration process val NOTIFY_USER = 1 val OPEN_BACKUP_MENU = 2 val PERFORM_BACKUP = 3 diff --git a/app/src/main/java/exh/ui/migration/manga/design/MigrationDesignController.kt b/app/src/main/java/exh/ui/migration/manga/design/MigrationDesignController.kt index 02b7463e8..8bb4da534 100644 --- a/app/src/main/java/exh/ui/migration/manga/design/MigrationDesignController.kt +++ b/app/src/main/java/exh/ui/migration/manga/design/MigrationDesignController.kt @@ -76,16 +76,16 @@ class MigrationDesignController(bundle: Bundle? = null) : BaseExhController(bund updateOptionsState() begin_migration_btn.setOnClickListener { - if(!showingOptions) { + if (!showingOptions) { showingOptions = true updateOptionsState() return@setOnClickListener } var flags = 0 - if(mig_chapters.isChecked) flags = flags or MigrationFlags.CHAPTERS - if(mig_categories.isChecked) flags = flags or MigrationFlags.CATEGORIES - if(mig_categories.isChecked) flags = flags or MigrationFlags.TRACK + if (mig_chapters.isChecked) flags = flags or MigrationFlags.CHAPTERS + if (mig_categories.isChecked) flags = flags or MigrationFlags.CATEGORIES + if (mig_categories.isChecked) flags = flags or MigrationFlags.TRACK router.replaceTopController(MigrationProcedureController.create( MigrationProcedureConfig( @@ -97,7 +97,7 @@ class MigrationDesignController(bundle: Bundle? = null) : BaseExhController(bund enableLenientSearch = use_smart_search.isChecked, migrationFlags = flags, copy = copy_manga.isChecked, - extraSearchParams = if(extra_search_param.isChecked && extra_search_param_text.text.isNotBlank()) { + extraSearchParams = if (extra_search_param.isChecked && extra_search_param_text.text.isNotBlank()) { extra_search_param_text.text.toString() } else null ) @@ -109,7 +109,7 @@ class MigrationDesignController(bundle: Bundle? = null) : BaseExhController(bund if (showingOptions) { begin_migration_btn.text = "Begin migration" options_group.visible() - if(extra_search_param.isChecked) { + if (extra_search_param.isChecked) { extra_search_param_text.visible() } else { extra_search_param_text.gone() @@ -122,7 +122,7 @@ class MigrationDesignController(bundle: Bundle? = null) : BaseExhController(bund } override fun handleBack(): Boolean { - if(showingOptions) { + if (showingOptions) { showingOptions = false updateOptionsState() return true @@ -142,7 +142,7 @@ class MigrationDesignController(bundle: Bundle? = null) : BaseExhController(bund } private fun updatePrioritizeChapterCount(migrationMode: Boolean) { - migration_mode.text = if(migrationMode) { + migration_mode.text = if (migrationMode) { "Currently using the source with the most chapters and the above list to break ties (slow with many sources or smart search)" } else { "Currently using the first source in the list that has the manga" @@ -182,4 +182,4 @@ class MigrationDesignController(bundle: Bundle? = null) : BaseExhController(bund }) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/ui/migration/manga/design/MigrationSourceAdapter.kt b/app/src/main/java/exh/ui/migration/manga/design/MigrationSourceAdapter.kt index 1a7eff5ee..622f2cb51 100644 --- a/app/src/main/java/exh/ui/migration/manga/design/MigrationSourceAdapter.kt +++ b/app/src/main/java/exh/ui/migration/manga/design/MigrationSourceAdapter.kt @@ -4,8 +4,10 @@ import android.os.Bundle import eu.davidea.flexibleadapter.FlexibleAdapter import exh.debug.DebugFunctions.sourceManager -class MigrationSourceAdapter(val items: List, - val controller: MigrationDesignController): FlexibleAdapter( +class MigrationSourceAdapter( + val items: List, + val controller: MigrationDesignController +) : FlexibleAdapter( items, controller, true @@ -29,4 +31,4 @@ class MigrationSourceAdapter(val items: List, companion object { private const val SELECTED_SOURCES_KEY = "selected_sources" } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/ui/migration/manga/design/MigrationSourceHolder.kt b/app/src/main/java/exh/ui/migration/manga/design/MigrationSourceHolder.kt index 8a7fcc6b7..0bb6c1bad 100644 --- a/app/src/main/java/exh/ui/migration/manga/design/MigrationSourceHolder.kt +++ b/app/src/main/java/exh/ui/migration/manga/design/MigrationSourceHolder.kt @@ -1,14 +1,14 @@ package exh.ui.migration.manga.design +import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG import android.view.View import eu.davidea.flexibleadapter.FlexibleAdapter import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder import eu.kanade.tachiyomi.util.view.getRound import kotlinx.android.synthetic.main.eh_source_item.* -import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG -class MigrationSourceHolder(view: View, val adapter: FlexibleAdapter): +class MigrationSourceHolder(view: View, val adapter: FlexibleAdapter) : BaseFlexibleViewHolder(view, adapter) { init { setDragHandleView(reorder) @@ -20,10 +20,10 @@ class MigrationSourceHolder(view: View, val adapter: FlexibleAdapter() { +class MigrationSourceItem(val source: HttpSource, var sourceEnabled: Boolean) : AbstractFlexibleItem() { override fun getLayoutRes() = R.layout.eh_source_item override fun createViewHolder(view: View, adapter: FlexibleAdapter>): MigrationSourceHolder { @@ -25,10 +25,12 @@ class MigrationSourceItem(val source: HttpSource, var sourceEnabled: Boolean): A * @param position The position of this item in the adapter. * @param payloads List of partial changes. */ - override fun bindViewHolder(adapter: FlexibleAdapter>, - holder: MigrationSourceHolder, - position: Int, - payloads: List?) { + override fun bindViewHolder( + adapter: FlexibleAdapter>, + holder: MigrationSourceHolder, + position: Int, + payloads: List? + ) { holder.bind(source, sourceEnabled) } @@ -52,7 +54,7 @@ class MigrationSourceItem(val source: HttpSource, var sourceEnabled: Boolean): A } @Parcelize - data class ParcelableSI(val sourceId: Long, val sourceEnabled: Boolean): Parcelable + data class ParcelableSI(val sourceId: Long, val sourceEnabled: Boolean) : Parcelable fun asParcelable(): ParcelableSI { return ParcelableSI(source.id, sourceEnabled) @@ -68,4 +70,4 @@ class MigrationSourceItem(val source: HttpSource, var sourceEnabled: Boolean): A ) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/ui/migration/manga/process/DeactivatableViewPager.kt b/app/src/main/java/exh/ui/migration/manga/process/DeactivatableViewPager.kt index 526c522f6..7c37eb4cd 100644 --- a/app/src/main/java/exh/ui/migration/manga/process/DeactivatableViewPager.kt +++ b/app/src/main/java/exh/ui/migration/manga/process/DeactivatableViewPager.kt @@ -5,8 +5,8 @@ import android.util.AttributeSet import android.view.MotionEvent class DeactivatableViewPager : androidx.viewpager.widget.ViewPager { - constructor(context: Context): super(context) - constructor(context: Context, attrs: AttributeSet): super(context, attrs) + constructor(context: Context) : super(context) + constructor(context: Context, attrs: AttributeSet) : super(context, attrs) override fun onTouchEvent(event: MotionEvent): Boolean { return !isEnabled || super.onTouchEvent(event) @@ -15,4 +15,4 @@ class DeactivatableViewPager : androidx.viewpager.widget.ViewPager { override fun onInterceptTouchEvent(event: MotionEvent): Boolean { return isEnabled && super.onInterceptTouchEvent(event) } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/ui/migration/manga/process/MigratingManga.kt b/app/src/main/java/exh/ui/migration/manga/process/MigratingManga.kt index 3707832e8..cd88de254 100644 --- a/app/src/main/java/exh/ui/migration/manga/process/MigratingManga.kt +++ b/app/src/main/java/exh/ui/migration/manga/process/MigratingManga.kt @@ -6,14 +6,17 @@ import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.SourceManager import exh.util.DeferredField import exh.util.await -import kotlinx.coroutines.* -import kotlinx.coroutines.channels.ConflatedBroadcastChannel import kotlin.coroutines.CoroutineContext +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.channels.ConflatedBroadcastChannel -class MigratingManga(private val db: DatabaseHelper, - private val sourceManager: SourceManager, - val mangaId: Long, - parentContext: CoroutineContext) { +class MigratingManga( + private val db: DatabaseHelper, + private val sourceManager: SourceManager, + val mangaId: Long, + parentContext: CoroutineContext +) { val searchResult = DeferredField() // @@ -24,11 +27,11 @@ class MigratingManga(private val db: DatabaseHelper, @Volatile private var manga: Manga? = null suspend fun manga(): Manga? { - if(manga == null) manga = db.getManga(mangaId).await() + if (manga == null) manga = db.getManga(mangaId).await() return manga } suspend fun mangaSource(): Source { return sourceManager.getOrStub(manga()?.source ?: -1) } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/ui/migration/manga/process/MigrationProcedureAdapter.kt b/app/src/main/java/exh/ui/migration/manga/process/MigrationProcedureAdapter.kt index 96f3953d7..5a4182278 100644 --- a/app/src/main/java/exh/ui/migration/manga/process/MigrationProcedureAdapter.kt +++ b/app/src/main/java/exh/ui/migration/manga/process/MigrationProcedureAdapter.kt @@ -22,20 +22,27 @@ import eu.kanade.tachiyomi.util.view.inflate import eu.kanade.tachiyomi.util.view.visible import exh.MERGED_SOURCE_ID import exh.util.await -import kotlinx.android.synthetic.main.eh_manga_card.view.* -import kotlinx.android.synthetic.main.eh_migration_process_item.view.* -import kotlinx.coroutines.* -import kotlinx.coroutines.flow.asFlow -import kotlinx.coroutines.flow.collect -import uy.kohesive.injekt.injectLazy import java.text.DateFormat import java.text.DecimalFormat -import java.util.* +import java.util.Date import kotlin.coroutines.CoroutineContext +import kotlinx.android.synthetic.main.eh_manga_card.view.* +import kotlinx.android.synthetic.main.eh_migration_process_item.view.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.asFlow +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import uy.kohesive.injekt.injectLazy -class MigrationProcedureAdapter(val controller: MigrationProcedureController, - val migratingManga: List, - override val coroutineContext: CoroutineContext) : androidx.viewpager.widget.PagerAdapter(), CoroutineScope { +class MigrationProcedureAdapter( + val controller: MigrationProcedureController, + val migratingManga: List, + override val coroutineContext: CoroutineContext +) : androidx.viewpager.widget.PagerAdapter(), CoroutineScope { private val db: DatabaseHelper by injectLazy() private val gson: Gson by injectLazy() private val sourceManager: SourceManager by injectLazy() @@ -69,7 +76,7 @@ class MigrationProcedureAdapter(val controller: MigrationProcedureController, performMigration(item) } controller.nextMigration() - } catch(e: Exception) { + } catch (e: Exception) { logger.e("Migration failure!", e) controller.migrationFailure() } @@ -81,7 +88,7 @@ class MigrationProcedureAdapter(val controller: MigrationProcedureController, } suspend fun performMigration(manga: MigratingManga) { - if(!manga.searchResult.initialized) { + if (!manga.searchResult.initialized) { return } @@ -96,9 +103,11 @@ class MigrationProcedureAdapter(val controller: MigrationProcedureController, } } - private fun migrateMangaInternal(prevManga: Manga, - manga: Manga, - replace: Boolean) { + private fun migrateMangaInternal( + prevManga: Manga, + manga: Manga, + replace: Boolean + ) { db.inTransaction { // Update chapters read if (MigrationFlags.hasChapters(controller.config.migrationFlags)) { @@ -147,7 +156,7 @@ class MigrationProcedureAdapter(val controller: MigrationProcedureController, tag.launch { val manga = migratingManga.manga() val source = migratingManga.mangaSource() - if(manga != null) { + if (manga != null) { withContext(Dispatchers.Main) { eh_manga_card_from.loading_group.gone() eh_manga_card_from.attachManga(tag, manga, source) @@ -174,7 +183,7 @@ class MigrationProcedureAdapter(val controller: MigrationProcedureController, sourceManager.get(it) } withContext(Dispatchers.Main) { - if(searchResult != null && resultSource != null) { + if (searchResult != null && resultSource != null) { eh_manga_card_to.loading_group.gone() eh_manga_card_to.attachManga(tag, searchResult, resultSource) eh_manga_card_to.setOnClickListener { @@ -263,7 +272,7 @@ class MigrationProcedureAdapter(val controller: MigrationProcedureController, (objectAsView.tag as? ViewTag)?.destroy() } - class ViewTag(parent: CoroutineContext): CoroutineScope { + class ViewTag(parent: CoroutineContext) : CoroutineScope { /** * The context of this scope. * Context is encapsulated by the scope and used for implementation of coroutine builders that are extensions on the scope. @@ -277,4 +286,4 @@ class MigrationProcedureAdapter(val controller: MigrationProcedureController, cancel() } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/ui/migration/manga/process/MigrationProcedureConfig.kt b/app/src/main/java/exh/ui/migration/manga/process/MigrationProcedureConfig.kt index d11b70bcc..cc9d41fbe 100644 --- a/app/src/main/java/exh/ui/migration/manga/process/MigrationProcedureConfig.kt +++ b/app/src/main/java/exh/ui/migration/manga/process/MigrationProcedureConfig.kt @@ -5,11 +5,11 @@ import kotlinx.android.parcel.Parcelize @Parcelize data class MigrationProcedureConfig( - val mangaIds: List, - val targetSourceIds: List, - val useSourceWithMostChapters: Boolean, - val enableLenientSearch: Boolean, - val migrationFlags: Int, - val copy: Boolean, - val extraSearchParams: String? -): Parcelable \ No newline at end of file + val mangaIds: List, + val targetSourceIds: List, + val useSourceWithMostChapters: Boolean, + val enableLenientSearch: Boolean, + val migrationFlags: Int, + val copy: Boolean, + val extraSearchParams: String? +) : Parcelable diff --git a/app/src/main/java/exh/ui/migration/manga/process/MigrationProcedureController.kt b/app/src/main/java/exh/ui/migration/manga/process/MigrationProcedureController.kt index c215c2dbd..991e1640b 100644 --- a/app/src/main/java/exh/ui/migration/manga/process/MigrationProcedureController.kt +++ b/app/src/main/java/exh/ui/migration/manga/process/MigrationProcedureController.kt @@ -15,13 +15,21 @@ import eu.kanade.tachiyomi.util.system.toast import exh.smartsearch.SmartSearchEngine import exh.ui.base.BaseExhController import exh.util.await +import java.util.concurrent.atomic.AtomicInteger import kotlinx.android.synthetic.main.eh_migration_process.* -import kotlinx.coroutines.* +import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.async +import kotlinx.coroutines.cancel +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.withPermit +import kotlinx.coroutines.withContext import rx.schedulers.Schedulers import uy.kohesive.injekt.injectLazy -import java.util.concurrent.atomic.AtomicInteger // TODO Will probably implode if activity is fully destroyed class MigrationProcedureController(bundle: Bundle? = null) : BaseExhController(bundle), CoroutineScope { @@ -70,7 +78,7 @@ class MigrationProcedureController(bundle: Bundle? = null) : BaseExhController(b pager.adapter = adapter pager.isEnabled = false - if(migrationsJob == null) { + if (migrationsJob == null) { migrationsJob = launch { runMigrations(newMigratingManga) } @@ -89,7 +97,7 @@ class MigrationProcedureController(bundle: Bundle? = null) : BaseExhController(b fun nextMigration() { adapter?.let { adapter -> - if(pager.currentItem >= adapter.count - 1) { + if (pager.currentItem >= adapter.count - 1) { applicationContext?.toast("All migrations complete!") router.popCurrentController() } else { @@ -115,11 +123,11 @@ class MigrationProcedureController(bundle: Bundle? = null) : BaseExhController(b suspend fun runMigrations(mangas: List) { val sources = config.targetSourceIds.mapNotNull { sourceManager.get(it) as? CatalogueSource } - for(manga in mangas) { - if(!manga.searchResult.initialized && manga.migrationJob.isActive) { + for (manga in mangas) { + if (!manga.searchResult.initialized && manga.migrationJob.isActive) { val mangaObj = manga.manga() - if(mangaObj == null) { + if (mangaObj == null) { manga.searchResult.initialize(null) continue } @@ -131,39 +139,39 @@ class MigrationProcedureController(bundle: Bundle? = null) : BaseExhController(b val validSources = sources.filter { it.id != mangaSource.id } - if(config.useSourceWithMostChapters) { + if (config.useSourceWithMostChapters) { val sourceSemaphore = Semaphore(3) val processedSources = AtomicInteger() validSources.map { source -> - async { - sourceSemaphore.withPermit { - try { - val searchResult = if (config.enableLenientSearch) { - smartSearchEngine.smartSearch(source, mangaObj.title) - } else { - smartSearchEngine.normalSearch(source, mangaObj.title) - } + async { + sourceSemaphore.withPermit { + try { + val searchResult = if (config.enableLenientSearch) { + smartSearchEngine.smartSearch(source, mangaObj.title) + } else { + smartSearchEngine.normalSearch(source, mangaObj.title) + } - if(searchResult != null) { - val localManga = smartSearchEngine.networkToLocalManga(searchResult, source.id) - val chapters = source.fetchChapterList(localManga).toSingle().await(Schedulers.io()) - withContext(Dispatchers.IO) { - syncChaptersWithSource(db, chapters, localManga, source) - } - manga.progress.send(validSources.size to processedSources.incrementAndGet()) - localManga to chapters.size - } else { - null - } - } catch(e: CancellationException) { - // Ignore cancellations - throw e - } catch(e: Exception) { - logger.e("Failed to search in source: ${source.id}!", e) - null - } - } + if (searchResult != null) { + val localManga = smartSearchEngine.networkToLocalManga(searchResult, source.id) + val chapters = source.fetchChapterList(localManga).toSingle().await(Schedulers.io()) + withContext(Dispatchers.IO) { + syncChaptersWithSource(db, chapters, localManga, source) + } + manga.progress.send(validSources.size to processedSources.incrementAndGet()) + localManga to chapters.size + } else { + null + } + } catch (e: CancellationException) { + // Ignore cancellations + throw e + } catch (e: Exception) { + logger.e("Failed to search in source: ${source.id}!", e) + null + } + } } }.mapNotNull { it.await() }.maxBy { it.second }?.first } else { @@ -183,28 +191,28 @@ class MigrationProcedureController(bundle: Bundle? = null) : BaseExhController(b } localManga } else null - } catch(e: CancellationException) { + } catch (e: CancellationException) { // Ignore cancellations throw e - } catch(e: Exception) { + } catch (e: Exception) { logger.e("Failed to search in source: ${source.id}!", e) null } manga.progress.send(validSources.size to (index + 1)) - if(searchResult != null) return@async searchResult + if (searchResult != null) return@async searchResult } null } }.await() - } catch(e: CancellationException) { + } catch (e: CancellationException) { // Ignore canceled migrations continue } - if(result != null && result.thumbnail_url == null) { + if (result != null && result.thumbnail_url == null) { try { val newManga = sourceManager.getOrStub(result.source) .fetchMangaDetails(result) @@ -213,10 +221,10 @@ class MigrationProcedureController(bundle: Bundle? = null) : BaseExhController(b result.copyFrom(newManga) db.insertManga(result).await() - } catch(e: CancellationException) { + } catch (e: CancellationException) { // Ignore cancellations throw e - } catch(e: Exception) { + } catch (e: Exception) { logger.e("Could not load search manga details", e) } } @@ -241,4 +249,4 @@ class MigrationProcedureController(bundle: Bundle? = null) : BaseExhController(b }) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/ui/smartsearch/SmartSearchController.kt b/app/src/main/java/exh/ui/smartsearch/SmartSearchController.kt index 99df0d297..911cc2067 100644 --- a/app/src/main/java/exh/ui/smartsearch/SmartSearchController.kt +++ b/app/src/main/java/exh/ui/smartsearch/SmartSearchController.kt @@ -14,7 +14,13 @@ import eu.kanade.tachiyomi.ui.catalogue.browse.BrowseCatalogueController import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.util.system.toast import kotlinx.android.synthetic.main.eh_smart_search.* -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.NonCancellable +import kotlinx.coroutines.cancel +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import uy.kohesive.injekt.injectLazy class SmartSearchController(bundle: Bundle? = null) : NucleusController(), CoroutineScope { @@ -37,7 +43,7 @@ class SmartSearchController(bundle: Bundle? = null) : NucleusController(), CoroutineScope { private val logger = XLog.tag("SmartSearchPresenter") @@ -24,7 +29,7 @@ class SmartSearchPresenter(private val source: CatalogueSource?, private val con override fun onCreate(savedState: Bundle?) { super.onCreate(savedState) - if(source != null && config != null) { + if (source != null && config != null) { launch(Dispatchers.Default) { val result = try { val resultManga = smartSearchEngine.smartSearch(source, config.origTitle) @@ -48,7 +53,6 @@ class SmartSearchPresenter(private val source: CatalogueSource?, private val con } } - override fun onDestroy() { super.onDestroy() @@ -58,8 +62,8 @@ class SmartSearchPresenter(private val source: CatalogueSource?, private val con data class SearchEntry(val manga: SManga, val dist: Double) sealed class SearchResults { - data class Found(val manga: Manga): SearchResults() - object NotFound: SearchResults() - object Error: SearchResults() + data class Found(val manga: Manga) : SearchResults() + object NotFound : SearchResults() + object Error : SearchResults() } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/util/CachedField.kt b/app/src/main/java/exh/util/CachedField.kt index 8b4fa1fc4..70ea8e449 100644 --- a/app/src/main/java/exh/util/CachedField.kt +++ b/app/src/main/java/exh/util/CachedField.kt @@ -14,7 +14,7 @@ class CachedField(private val expiresAfterMs: Long) { suspend fun obtain(producer: suspend () -> T): T { return mutex.withLock { - if(initTime < 0 || System.currentTimeMillis() - initTime > expiresAfterMs) { + if (initTime < 0 || System.currentTimeMillis() - initTime > expiresAfterMs) { content = producer() } diff --git a/app/src/main/java/exh/util/CoroutineUtil.kt b/app/src/main/java/exh/util/CoroutineUtil.kt index b9c55bb41..39ec95bfb 100644 --- a/app/src/main/java/exh/util/CoroutineUtil.kt +++ b/app/src/main/java/exh/util/CoroutineUtil.kt @@ -1,12 +1,12 @@ package exh.util +import kotlin.coroutines.coroutineContext import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.ensureActive import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.onEach -import kotlin.coroutines.coroutineContext @FlowPreview fun Flow.cancellable() = onEach { coroutineContext.ensureActive() -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/util/DeferredField.kt b/app/src/main/java/exh/util/DeferredField.kt index bbaf501a3..9b09ec97b 100644 --- a/app/src/main/java/exh/util/DeferredField.kt +++ b/app/src/main/java/exh/util/DeferredField.kt @@ -35,7 +35,7 @@ class DeferredField { */ suspend fun get(): T { // Check if field is initialized and return immediately if it is - if(initialized) return content as T + if (initialized) return content as T // Wait for field to initialize mutex.withLock {} @@ -43,4 +43,4 @@ class DeferredField { // Field is initialized, return value return content as T } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/util/ExceptionUtil.kt b/app/src/main/java/exh/util/ExceptionUtil.kt index 084523106..3b73328a3 100644 --- a/app/src/main/java/exh/util/ExceptionUtil.kt +++ b/app/src/main/java/exh/util/ExceptionUtil.kt @@ -7,11 +7,11 @@ inline fun ignore(expr: () -> T): T? { fun T.withRootCause(cause: Throwable): T { val curCause = this.cause - if(curCause == null) { + if (curCause == null) { this.initCause(cause) } else { curCause.withRootCause(cause) } return this -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/util/FakeMutables.kt b/app/src/main/java/exh/util/FakeMutables.kt index 23b4fd215..e8d2d268c 100644 --- a/app/src/main/java/exh/util/FakeMutables.kt +++ b/app/src/main/java/exh/util/FakeMutables.kt @@ -112,7 +112,6 @@ private inline class IteratorShim(private val iterator: Iterator) : FakeMu override fun next() = iterator.next() } - interface FakeMutableIterator : MutableIterator { /** * Removes from the underlying collection the last element returned by this iterator. @@ -122,7 +121,7 @@ interface FakeMutableIterator : MutableIterator { } companion object { - fun fromIterator(iterator: Iterator) : FakeMutableIterator = IteratorShim(iterator) + fun fromIterator(iterator: Iterator): FakeMutableIterator = IteratorShim(iterator) } } @@ -171,4 +170,4 @@ interface FakeMutableEntry : MutableMap.MutableEntry { override val value: V = value } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/util/JsonReaderObjectReader.kt b/app/src/main/java/exh/util/JsonReaderObjectReader.kt index 383a587cf..c730f1049 100644 --- a/app/src/main/java/exh/util/JsonReaderObjectReader.kt +++ b/app/src/main/java/exh/util/JsonReaderObjectReader.kt @@ -18,10 +18,10 @@ fun JsonReader.nextJsonObject(): JsonObject { val obj = JsonObject() - while(hasNext()) { + while (hasNext()) { val name = nextName() - when(peek()) { + when (peek()) { JsonToken.BEGIN_ARRAY -> obj.add(name, nextJsonArray()) JsonToken.BEGIN_OBJECT -> obj.add(name, nextJsonObject()) JsonToken.NULL -> { @@ -45,8 +45,8 @@ fun JsonReader.nextJsonArray(): JsonArray { val arr = JsonArray() - while(hasNext()) { - when(peek()) { + while (hasNext()) { + when (peek()) { JsonToken.BEGIN_ARRAY -> arr.add(nextJsonArray()) JsonToken.BEGIN_OBJECT -> arr.add(nextJsonObject()) JsonToken.NULL -> { diff --git a/app/src/main/java/exh/util/LoggingRealmQuery.kt b/app/src/main/java/exh/util/LoggingRealmQuery.kt index 97d19c400..cdddbc563 100644 --- a/app/src/main/java/exh/util/LoggingRealmQuery.kt +++ b/app/src/main/java/exh/util/LoggingRealmQuery.kt @@ -1,7 +1,10 @@ package exh.util -import io.realm.* -import java.util.* +import io.realm.Case +import io.realm.RealmModel +import io.realm.RealmQuery +import io.realm.RealmResults +import java.util.Date /** * Realm query with logging @@ -9,14 +12,16 @@ import java.util.* * @author nulldev */ -inline fun RealmQuery.beginLog(clazz: Class? = - E::class.java): LoggingRealmQuery - = LoggingRealmQuery.fromQuery(this, clazz) +inline fun RealmQuery.beginLog( + clazz: Class? = +E::class.java +): LoggingRealmQuery = + LoggingRealmQuery.fromQuery(this, clazz) class LoggingRealmQuery(val query: RealmQuery) { companion object { - fun fromQuery(q: RealmQuery, clazz: Class?) - = LoggingRealmQuery(q).apply { + fun fromQuery(q: RealmQuery, clazz: Class?) = + LoggingRealmQuery(q).apply { log += "SELECT * FROM ${clazz?.name ?: "???"} WHERE" } } diff --git a/app/src/main/java/exh/util/NakedTrie.kt b/app/src/main/java/exh/util/NakedTrie.kt index f6f2e5523..2eddb90a2 100644 --- a/app/src/main/java/exh/util/NakedTrie.kt +++ b/app/src/main/java/exh/util/NakedTrie.kt @@ -1,7 +1,8 @@ package exh.util import android.util.SparseArray -import java.util.* +import java.util.AbstractMap +import java.util.LinkedList class NakedTrieNode(val key: Int, var parent: NakedTrieNode?) { val children = SparseArray>(1) @@ -12,30 +13,30 @@ class NakedTrieNode(val key: Int, var parent: NakedTrieNode?) { // 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 + 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()) { + 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 + 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) { + for (c in key) { current = current.children.get(c.toInt()) ?: return null - if(!current.hasData) return null + if (!current.hasData) return null } return current } @@ -72,10 +73,10 @@ class NakedTrie : MutableMap { 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) { + for (c in key) { val castedC = c.toInt() var node = current.children.get(castedC) - if(node == null) { + if (node == null) { node = NakedTrieNode(castedC, current) current.children.put(castedC, node) } @@ -83,7 +84,7 @@ class NakedTrie : MutableMap { } // Add data to node or replace existing data - val previous = if(current.hasData) { + val previous = if (current.hasData) { current.data } else { current.hasData = true @@ -99,7 +100,7 @@ class NakedTrie : MutableMap { override fun get(key: String): T? { val current = getAsNode(key) ?: return null - return if(current.hasData) current.data else null + return if (current.hasData) current.data else null } fun getAsNode(key: String): NakedTrieNode? { @@ -108,9 +109,9 @@ class NakedTrie : MutableMap { override fun containsKey(key: String): Boolean { var current = root - for(c in key) { + for (c in key) { current = current.children.get(c.toInt()) ?: return false - if(!current.hasData) return false + if (!current.hasData) return false } return current.hasData } @@ -123,10 +124,10 @@ class NakedTrie : MutableMap { 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) { + for (c in key) { val bottomOfStack = nodeStack.last val current = bottomOfStack.children.get(c.toInt()) ?: return null - if(!current.hasData) return null + if (!current.hasData) return null nodeStack.add(bottomOfStack) } @@ -137,9 +138,9 @@ class NakedTrie : MutableMap { bottomOfStack.data = null // Clear data field for GC // Remove nodes that we visited that are useless - for(curBottom in nodeStack.descendingIterator()) { + for (curBottom in nodeStack.descendingIterator()) { val parent = curBottom.parent ?: break - if(!curBottom.hasData && curBottom.children.size() <= 0) { + if (!curBottom.hasData && curBottom.children.size() <= 0) { // No data or child nodes, this node is useless, discard parent.children.remove(curBottom.key) } else break @@ -176,10 +177,10 @@ class NakedTrie : MutableMap { 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) { + for (c in key) { val castedC = c.toInt() var node = current.children.get(castedC) - if(node == null) { + if (node == null) { node = NakedTrieNode(castedC, current) current.children.put(castedC, node) } @@ -187,7 +188,7 @@ class NakedTrie : MutableMap { } // Add data to node or replace existing data - if(!current.hasData) { + if (!current.hasData) { current.hasData = true current.data = producer() size++ @@ -253,7 +254,7 @@ class NakedTrie : MutableMap { * Returns `true` if the map contains the specified [key]. */ override fun containsKey(key: String): Boolean { - if(!key.startsWith(prefix)) return false + if (!key.startsWith(prefix)) return false val childNode = node.getAsNode(key.removePrefix(prefix)) ?: return false return childNode.hasData && (!leavesOnly || childNode.children.size() <= 0) @@ -264,7 +265,7 @@ class NakedTrie : MutableMap { */ override fun containsValue(value: T): Boolean { node.walk("", { _, v -> - if(v == value) return true + if (v == value) return true true }, leavesOnly) return false @@ -274,10 +275,10 @@ class NakedTrie : MutableMap { * 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 + 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 + if (!childNode.hasData || (leavesOnly && childNode.children.size() > 0)) return null return childNode.data } @@ -285,8 +286,8 @@ class NakedTrie : MutableMap { * 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 + if (node.children.size() <= 0 && !root.hasData) return true + if (!leavesOnly) return false node.walk("", { _, _ -> return false }, leavesOnly) return true } @@ -300,7 +301,7 @@ class NakedTrie : MutableMap { */ override fun containsValue(value: T): Boolean { walk { _, t -> - if(t == value) { + if (t == value) { return true } @@ -342,4 +343,4 @@ class NakedTrie : MutableMap { true } }) -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/util/OkHttpUtil.kt b/app/src/main/java/exh/util/OkHttpUtil.kt index b152850de..05fbf058b 100644 --- a/app/src/main/java/exh/util/OkHttpUtil.kt +++ b/app/src/main/java/exh/util/OkHttpUtil.kt @@ -8,8 +8,8 @@ import org.jsoup.nodes.Document fun Response.interceptAsHtml(block: (Document) -> Unit): Response { val body = body - if (body?.contentType()?.type == "text" - && body.contentType()?.subtype == "html") { + if (body?.contentType()?.type == "text" && + body.contentType()?.subtype == "html") { val bodyString = body.string() val rebuiltResponse = newBuilder() .body(ResponseBody.create(body.contentType(), bodyString)) @@ -28,4 +28,4 @@ fun Response.interceptAsHtml(block: (Document) -> Unit): Response { return rebuiltResponse } return this -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/util/RealmUtil.kt b/app/src/main/java/exh/util/RealmUtil.kt index 1062e1390..91c510579 100644 --- a/app/src/main/java/exh/util/RealmUtil.kt +++ b/app/src/main/java/exh/util/RealmUtil.kt @@ -3,7 +3,7 @@ package exh.util import io.realm.Realm import io.realm.RealmModel import io.realm.log.RealmLog -import java.util.* +import java.util.UUID inline fun realmTrans(block: (Realm) -> T): T { return defRealm { @@ -25,7 +25,7 @@ inline fun Realm.trans(block: () -> T): T { val res = block() commitTransaction() return res - } catch(t: Throwable) { + } catch (t: Throwable) { if (isInTransaction) { cancelTransaction() } else { @@ -34,7 +34,7 @@ inline fun Realm.trans(block: () -> T): T { throw t } finally { - //Just in case + // Just in case if (isInTransaction) { cancelTransaction() } @@ -49,9 +49,8 @@ inline fun Realm.useTrans(block: (Realm) -> T): T { } } -fun Realm.createUUIDObj(clazz: Class) - = createObject(clazz, UUID.randomUUID().toString())!! - -inline fun Realm.createUUIDObj() - = createUUIDObj(T::class.java) +fun Realm.createUUIDObj(clazz: Class) = + createObject(clazz, UUID.randomUUID().toString())!! +inline fun Realm.createUUIDObj() = + createUUIDObj(T::class.java) diff --git a/app/src/main/java/exh/util/RxUtil.kt b/app/src/main/java/exh/util/RxUtil.kt index 6ef915e75..1028d7da1 100644 --- a/app/src/main/java/exh/util/RxUtil.kt +++ b/app/src/main/java/exh/util/RxUtil.kt @@ -2,10 +2,14 @@ package exh.util import com.pushtorefresh.storio.operations.PreparedOperation import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetObject -import kotlinx.coroutines.suspendCancellableCoroutine -import rx.* -import rx.subjects.ReplaySubject import kotlin.coroutines.resumeWithException +import kotlinx.coroutines.suspendCancellableCoroutine +import rx.Completable +import rx.Observable +import rx.Scheduler +import rx.Single +import rx.Subscription +import rx.subjects.ReplaySubject /** * Transform a cold single to a hot single diff --git a/app/src/main/java/exh/util/SearchOverride.kt b/app/src/main/java/exh/util/SearchOverride.kt index 0fefe81a9..7573a4a12 100644 --- a/app/src/main/java/exh/util/SearchOverride.kt +++ b/app/src/main/java/exh/util/SearchOverride.kt @@ -18,7 +18,7 @@ fun UrlImportableSource.urlImportFetchSearchManga(query: String, fail: () -> Obs query.startsWith("http://") || query.startsWith("https://") -> { Observable.fromCallable { val res = galleryAdder.addGallery(query, false, this) - MangasPage((if(res is GalleryAddEvent.Success) + MangasPage((if (res is GalleryAddEvent.Success) listOf(res.manga) else emptyList()), false) diff --git a/app/src/main/java/exh/util/SparseArrayCollection.kt b/app/src/main/java/exh/util/SparseArrayCollection.kt index cad104ab3..bfe1acbad 100644 --- a/app/src/main/java/exh/util/SparseArrayCollection.kt +++ b/app/src/main/java/exh/util/SparseArrayCollection.kt @@ -3,7 +3,7 @@ package exh.util import android.util.SparseArray import java.util.AbstractMap -class SparseArrayKeyCollection(val sparseArray: SparseArray, var reverse: Boolean = false): AbstractCollection() { +class SparseArrayKeyCollection(val sparseArray: SparseArray, var reverse: Boolean = false) : AbstractCollection() { override val size get() = sparseArray.size() override fun iterator() = object : Iterator { @@ -19,13 +19,13 @@ class SparseArrayKeyCollection(val sparseArray: SparseArray, var rever */ override fun next(): Int { var idx = index++ - if(reverse) idx = sparseArray.size() - 1 - idx + if (reverse) idx = sparseArray.size() - 1 - idx return sparseArray.keyAt(idx) } } } -class SparseArrayValueCollection(val sparseArray: SparseArray, var reverse: Boolean = false): AbstractCollection() { +class SparseArrayValueCollection(val sparseArray: SparseArray, var reverse: Boolean = false) : AbstractCollection() { override val size get() = sparseArray.size() override fun iterator() = object : Iterator { @@ -41,13 +41,13 @@ class SparseArrayValueCollection(val sparseArray: SparseArray, var reverse */ override fun next(): E { var idx = index++ - if(reverse) idx = sparseArray.size() - 1 - idx + if (reverse) idx = sparseArray.size() - 1 - idx return sparseArray.valueAt(idx) } } } -class SparseArrayCollection(val sparseArray: SparseArray, var reverse: Boolean = false): AbstractCollection>() { +class SparseArrayCollection(val sparseArray: SparseArray, var reverse: Boolean = false) : AbstractCollection>() { override val size get() = sparseArray.size() override fun iterator() = object : Iterator> { @@ -63,7 +63,7 @@ class SparseArrayCollection(val sparseArray: SparseArray, var reverse: Boo */ override fun next(): Map.Entry { var idx = index++ - if(reverse) idx = sparseArray.size() - 1 - idx + 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/UriFilter.kt b/app/src/main/java/exh/util/UriFilter.kt index 655b03996..5b16592f1 100755 --- a/app/src/main/java/exh/util/UriFilter.kt +++ b/app/src/main/java/exh/util/UriFilter.kt @@ -7,4 +7,4 @@ import android.net.Uri */ interface UriFilter { fun addToUri(builder: Uri.Builder) -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/util/UriGroup.kt b/app/src/main/java/exh/util/UriGroup.kt index cb9225c40..f066b0d44 100755 --- a/app/src/main/java/exh/util/UriGroup.kt +++ b/app/src/main/java/exh/util/UriGroup.kt @@ -9,7 +9,7 @@ import eu.kanade.tachiyomi.source.model.Filter open class UriGroup(name: String, state: List) : Filter.Group(name, state), UriFilter { override fun addToUri(builder: Uri.Builder) { state.forEach { - if(it is UriFilter) it.addToUri(builder) + if (it is UriFilter) it.addToUri(builder) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/exh/util/ViewUtil.kt b/app/src/main/java/exh/util/ViewUtil.kt index edd35d1a9..4d4e98bc1 100644 --- a/app/src/main/java/exh/util/ViewUtil.kt +++ b/app/src/main/java/exh/util/ViewUtil.kt @@ -5,4 +5,4 @@ import android.content.Context fun dpToPx(context: Context, dp: Int): Int { val scale = context.resources.displayMetrics.density return (dp * scale + 0.5f).toInt() -} \ No newline at end of file +} diff --git a/app/src/main/java/org/vepta/vdm/ByteCursor.kt b/app/src/main/java/org/vepta/vdm/ByteCursor.kt index bd6e5e17e..cd18f9f51 100644 --- a/app/src/main/java/org/vepta/vdm/ByteCursor.kt +++ b/app/src/main/java/org/vepta/vdm/ByteCursor.kt @@ -10,80 +10,80 @@ 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) + val res = content.sliceArray(index + 1..index + count) skip(count) return res } - - //Used to perform conversions + + // Used to perform conversions private fun byteBuffer(count: Int): ByteBuffer { return ByteBuffer.wrap(next(count)) } - - //Epic hack to get an unsigned short properly... + + // 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()) + if (bytes.size > remaining()) throw IllegalStateException("Unexpected end of content!") - - for(i in 0 .. bytes.lastIndex) { + + for (i in 0..bytes.lastIndex) { val expected = bytes[i] val actual = content[index + i + 1] - - if(expected != actual) + + if (expected != actual) throw IllegalStateException("Unexpected content (expected: $expected, actual: $actual)!") } - + index += bytes.size } - + fun checkEqual(vararg bytes: Byte): Boolean { - if(bytes.size > remaining()) + if (bytes.size > remaining()) return false - - for(i in 0 .. bytes.lastIndex) { + + for (i in 0..bytes.lastIndex) { val expected = bytes[i] val actual = content[index + i + 1] - - if(expected != actual) + + if (expected != actual) return false } - + return true } - + fun atEnd() = index >= content.size - 1 - + fun remaining() = content.size - index - 1 -} \ No newline at end of file +} 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 c72d69f0f..e94e4098c 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 @@ -1,6 +1,17 @@ package xyz.nulldev.ts.api.http.serializer -import com.github.salomonbrys.kotson.* +import com.github.salomonbrys.kotson.bool +import com.github.salomonbrys.kotson.byte +import com.github.salomonbrys.kotson.char +import com.github.salomonbrys.kotson.double +import com.github.salomonbrys.kotson.float +import com.github.salomonbrys.kotson.get +import com.github.salomonbrys.kotson.int +import com.github.salomonbrys.kotson.long +import com.github.salomonbrys.kotson.obj +import com.github.salomonbrys.kotson.set +import com.github.salomonbrys.kotson.short +import com.github.salomonbrys.kotson.string import com.google.gson.JsonArray import com.google.gson.JsonObject import eu.kanade.tachiyomi.source.model.Filter @@ -31,9 +42,9 @@ class FilterSerializer { fun serialize(filter: Filter): JsonObject { val out = JsonObject() - for(serializer in serializers) { - if(filter::class.isSubclassOf(serializer.clazz)) { - //TODO Not sure how to deal with the mess of types here + for (serializer in serializers) { + if (filter::class.isSubclassOf(serializer.clazz)) { + // TODO Not sure how to deal with the mess of types here serializer as Serializer> serializer.serialize(out, filter) @@ -65,15 +76,15 @@ class FilterSerializer { it.type == json[TYPE].string } ?: throw IllegalArgumentException("Cannot deserialize this type!") - //TODO Not sure how to deal with the mess of types here + // TODO Not sure how to deal with the mess of types here serializer as Serializer> serializer.deserialize(json, filter) serializer.mappings().forEach { - if(it.second is KMutableProperty1) { + if (it.second is KMutableProperty1) { val obj = json[it.first] - val res: Any? = when(json[CLASS_MAPPINGS][it.first].string) { + val res: Any? = when (json[CLASS_MAPPINGS][it.first].string) { java.lang.Integer::class.java.name -> obj.int java.lang.Long::class.java.name -> obj.long java.lang.Float::class.java.name -> obj.float diff --git a/app/src/main/java/xyz/nulldev/ts/api/http/serializer/FilterSerializerModels.kt b/app/src/main/java/xyz/nulldev/ts/api/http/serializer/FilterSerializerModels.kt index 676209083..aa3eaa40f 100644 --- a/app/src/main/java/xyz/nulldev/ts/api/http/serializer/FilterSerializerModels.kt +++ b/app/src/main/java/xyz/nulldev/ts/api/http/serializer/FilterSerializerModels.kt @@ -75,7 +75,7 @@ class SelectSerializer(override val serializer: FilterSerializer) : Serializer) { - //Serialize values to JSON + // Serialize values to JSON json[VALUES] = JsonArray().apply { filter.values.map { it.toString() @@ -147,7 +147,7 @@ class GroupSerializer(override val serializer: FilterSerializer) : Serializer) { json[STATE] = JsonArray().apply { filter.state.forEach { - add(if(it is Filter<*>) + add(if (it is Filter<*>) serializer.serialize(it as Filter) else JsonNull.INSTANCE @@ -158,7 +158,7 @@ class GroupSerializer(override val serializer: FilterSerializer) : Serializer) { json[STATE].asJsonArray.forEachIndexed { index, jsonElement -> - if(!jsonElement.isJsonNull) + if (!jsonElement.isJsonNull) serializer.deserialize(filter.state[index] as Filter, jsonElement.asJsonObject) } } @@ -178,12 +178,12 @@ class SortSerializer(override val serializer: FilterSerializer) : Serializer JsonObject().apply { this[STATE_INDEX] = index @@ -193,7 +193,7 @@ class SortSerializer(override val serializer: FilterSerializer) : Serializer