From 86fe85079413f8ed6e1109b46e6131a9b788b988 Mon Sep 17 00:00:00 2001 From: Andreas Date: Fri, 16 Sep 2022 00:12:27 +0200 Subject: [PATCH] Extract source api from app module (#8014) * Extract source api from app module * Extract source online api from app module --- app/build.gradle.kts | 2 + .../tachiyomi/data/backup/BackupManager.kt | 1 + .../data/preference/PreferencesHelper.kt | 1 + .../tachiyomi/source/SourceExtensions.kt | 31 +++++++++++++ .../source/model/SChapterExtensions.kt | 11 +++++ .../source/model/SMangaExtensions.kt | 31 +++++++++++++ .../setting/SettingsAppearanceController.kt | 1 + .../util/system/ContextExtensions.kt | 25 ---------- .../util/system/DeviceUtilExtensions.kt | 8 ++++ core/.gitignore | 1 + core/build.gradle.kts | 46 +++++++++++++++++++ core/src/main/AndroidManifest.xml | 2 + .../tachiyomi/network/AndroidCookieJar.kt | 0 .../kanade/tachiyomi/network/DohProviders.kt | 0 .../kanade/tachiyomi/network/NetworkHelper.kt | 12 ++--- .../tachiyomi/network/OkHttpExtensions.kt | 0 .../tachiyomi/network/ProgressListener.kt | 0 .../tachiyomi/network/ProgressResponseBody.kt | 0 .../eu/kanade/tachiyomi/network/Requests.kt | 2 +- .../interceptor/CloudflareInterceptor.kt | 2 +- .../network/interceptor/Http103Interceptor.kt | 0 .../interceptor/RateLimitInterceptor.kt | 0 .../SpecificHostRateLimitInterceptor.kt | 0 .../interceptor/UserAgentInterceptor.kt | 0 .../network/interceptor/WebViewInterceptor.kt | 2 +- .../util/lang/CoroutinesExtensions.kt | 0 .../tachiyomi/util/lang/RxCoroutineBridge.kt | 2 + .../tachiyomi/util/system/DeviceUtil.kt | 5 -- .../tachiyomi/util/system/LogcatExtensions.kt | 0 .../tachiyomi/util/system/ToastExtensions.kt | 28 +++++++++++ .../util/system/WebViewClientCompat.kt | 0 .../tachiyomi/util/system/WebViewUtil.kt | 0 settings.gradle.kts | 2 + source-api/.gitignore | 1 + source-api/build.gradle.kts | 39 ++++++++++++++++ source-api/src/main/AndroidManifest.xml | 2 + .../tachiyomi/source/CatalogueSource.kt | 0 .../tachiyomi/source/ConfigurableSource.kt | 0 .../java/eu/kanade/tachiyomi/source/Source.kt | 29 ------------ .../kanade/tachiyomi/source/SourceFactory.kt | 0 .../tachiyomi/source/UnmeteredSource.kt | 0 .../kanade/tachiyomi/source/model/Filter.kt | 0 .../tachiyomi/source/model/FilterList.kt | 0 .../tachiyomi/source/model/MangasPage.kt | 0 .../eu/kanade/tachiyomi/source/model/Page.kt | 0 .../kanade/tachiyomi/source/model/SChapter.kt | 9 ---- .../tachiyomi/source/model/SChapterImpl.kt | 0 .../kanade/tachiyomi/source/model/SManga.kt | 29 ------------ .../tachiyomi/source/model/SMangaImpl.kt | 0 .../tachiyomi/source/online/HttpSource.kt | 0 .../source/online/HttpSourceFetcher.kt | 0 .../source/online/ParsedHttpSource.kt | 1 + .../kanade/tachiyomi/util/JsoupExtensions.kt | 0 53 files changed, 219 insertions(+), 106 deletions(-) create mode 100644 app/src/main/java/eu/kanade/tachiyomi/source/SourceExtensions.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/source/model/SChapterExtensions.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/source/model/SMangaExtensions.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtilExtensions.kt create mode 100644 core/.gitignore create mode 100644 core/build.gradle.kts create mode 100644 core/src/main/AndroidManifest.xml rename {app => core}/src/main/java/eu/kanade/tachiyomi/network/AndroidCookieJar.kt (100%) rename {app => core}/src/main/java/eu/kanade/tachiyomi/network/DohProviders.kt (100%) rename {app => core}/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt (85%) rename {app => core}/src/main/java/eu/kanade/tachiyomi/network/OkHttpExtensions.kt (100%) rename {app => core}/src/main/java/eu/kanade/tachiyomi/network/ProgressListener.kt (100%) rename {app => core}/src/main/java/eu/kanade/tachiyomi/network/ProgressResponseBody.kt (100%) rename {app => core}/src/main/java/eu/kanade/tachiyomi/network/Requests.kt (95%) rename {app => core}/src/main/java/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt (99%) rename {app => core}/src/main/java/eu/kanade/tachiyomi/network/interceptor/Http103Interceptor.kt (100%) rename {app => core}/src/main/java/eu/kanade/tachiyomi/network/interceptor/RateLimitInterceptor.kt (100%) rename {app => core}/src/main/java/eu/kanade/tachiyomi/network/interceptor/SpecificHostRateLimitInterceptor.kt (100%) rename {app => core}/src/main/java/eu/kanade/tachiyomi/network/interceptor/UserAgentInterceptor.kt (100%) rename {app => core}/src/main/java/eu/kanade/tachiyomi/network/interceptor/WebViewInterceptor.kt (98%) rename {app => core}/src/main/java/eu/kanade/tachiyomi/util/lang/CoroutinesExtensions.kt (100%) rename {app => core}/src/main/java/eu/kanade/tachiyomi/util/lang/RxCoroutineBridge.kt (97%) rename {app => core}/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtil.kt (86%) rename {app => core}/src/main/java/eu/kanade/tachiyomi/util/system/LogcatExtensions.kt (100%) create mode 100644 core/src/main/java/eu/kanade/tachiyomi/util/system/ToastExtensions.kt rename {app => core}/src/main/java/eu/kanade/tachiyomi/util/system/WebViewClientCompat.kt (100%) rename {app => core}/src/main/java/eu/kanade/tachiyomi/util/system/WebViewUtil.kt (100%) create mode 100644 source-api/.gitignore create mode 100644 source-api/build.gradle.kts create mode 100644 source-api/src/main/AndroidManifest.xml rename {app => source-api}/src/main/java/eu/kanade/tachiyomi/source/CatalogueSource.kt (100%) rename {app => source-api}/src/main/java/eu/kanade/tachiyomi/source/ConfigurableSource.kt (100%) rename {app => source-api}/src/main/java/eu/kanade/tachiyomi/source/Source.kt (64%) rename {app => source-api}/src/main/java/eu/kanade/tachiyomi/source/SourceFactory.kt (100%) rename {app => source-api}/src/main/java/eu/kanade/tachiyomi/source/UnmeteredSource.kt (100%) rename {app => source-api}/src/main/java/eu/kanade/tachiyomi/source/model/Filter.kt (100%) rename {app => source-api}/src/main/java/eu/kanade/tachiyomi/source/model/FilterList.kt (100%) rename {app => source-api}/src/main/java/eu/kanade/tachiyomi/source/model/MangasPage.kt (100%) rename {app => source-api}/src/main/java/eu/kanade/tachiyomi/source/model/Page.kt (100%) rename {app => source-api}/src/main/java/eu/kanade/tachiyomi/source/model/SChapter.kt (70%) rename {app => source-api}/src/main/java/eu/kanade/tachiyomi/source/model/SChapterImpl.kt (100%) rename {app => source-api}/src/main/java/eu/kanade/tachiyomi/source/model/SManga.kt (72%) rename {app => source-api}/src/main/java/eu/kanade/tachiyomi/source/model/SMangaImpl.kt (100%) rename {app => source-api}/src/main/java/eu/kanade/tachiyomi/source/online/HttpSource.kt (100%) rename {app => source-api}/src/main/java/eu/kanade/tachiyomi/source/online/HttpSourceFetcher.kt (100%) rename {app => source-api}/src/main/java/eu/kanade/tachiyomi/source/online/ParsedHttpSource.kt (99%) rename {app => source-api}/src/main/java/eu/kanade/tachiyomi/util/JsoupExtensions.kt (100%) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2e3b7469b2..cfb3479463 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -150,6 +150,8 @@ android { dependencies { implementation(project(":i18n")) + implementation(project(":core")) + implementation(project(":source-api")) // Compose implementation(compose.activity) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt index 3e45a94b09..5d589b97cd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt @@ -33,6 +33,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.source.SourceManager +import eu.kanade.tachiyomi.source.model.copyFrom import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.toLong import kotlinx.serialization.protobuf.ProtoBuf diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 8432fe4f52..93c0eee419 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -19,6 +19,7 @@ import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType import eu.kanade.tachiyomi.util.system.DeviceUtil import eu.kanade.tachiyomi.util.system.LocaleHelper import eu.kanade.tachiyomi.util.system.isDevFlavor +import eu.kanade.tachiyomi.util.system.isDynamicColorAvailable import eu.kanade.tachiyomi.widget.ExtendedNavigationView import java.io.File import java.text.DateFormat diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/SourceExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/source/SourceExtensions.kt new file mode 100644 index 0000000000..f6bff12f04 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/source/SourceExtensions.kt @@ -0,0 +1,31 @@ +package eu.kanade.tachiyomi.source + +import android.graphics.drawable.Drawable +import eu.kanade.domain.source.model.SourceData +import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import eu.kanade.tachiyomi.extension.ExtensionManager +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get + +fun Source.icon(): Drawable? = Injekt.get().getAppIconForSource(this) + +fun Source.getPreferenceKey(): String = "source_$id" + +fun Source.toSourceData(): SourceData = SourceData(id = id, lang = lang, name = name) + +fun Source.getNameForMangaInfo(): String { + val preferences = Injekt.get() + val enabledLanguages = preferences.enabledLanguages().get() + .filterNot { it in listOf("all", "other") } + val hasOneActiveLanguages = enabledLanguages.size == 1 + val isInEnabledLanguages = lang in enabledLanguages + return when { + // For edge cases where user disables a source they got manga of in their library. + hasOneActiveLanguages && !isInEnabledLanguages -> toString() + // Hide the language tag when only one language is used. + hasOneActiveLanguages && isInEnabledLanguages -> name + else -> toString() + } +} + +fun Source.isLocalOrStub(): Boolean = id == LocalSource.ID || this is SourceManager.StubSource diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/model/SChapterExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/source/model/SChapterExtensions.kt new file mode 100644 index 0000000000..c54f782344 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/source/model/SChapterExtensions.kt @@ -0,0 +1,11 @@ +package eu.kanade.tachiyomi.source.model + +import data.Chapters + +fun SChapter.copyFrom(other: Chapters) { + name = other.name + url = other.url + date_upload = other.date_upload + chapter_number = other.chapter_number + scanlator = other.scanlator +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/model/SMangaExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/source/model/SMangaExtensions.kt new file mode 100644 index 0000000000..7df175fc55 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/source/model/SMangaExtensions.kt @@ -0,0 +1,31 @@ +package eu.kanade.tachiyomi.source.model + +import data.Mangas + +fun SManga.copyFrom(other: Mangas) { + if (other.author != null) { + author = other.author + } + + if (other.artist != null) { + artist = other.artist + } + + if (other.description != null) { + description = other.description + } + + if (other.genre != null) { + genre = other.genre.joinToString(separator = ", ") + } + + if (other.thumbnail_url != null) { + thumbnail_url = other.thumbnail_url + } + + status = other.status.toInt() + + if (!initialized) { + initialized = other.initialized + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAppearanceController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAppearanceController.kt index a89885fc54..8f2ee0c30e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAppearanceController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAppearanceController.kt @@ -17,6 +17,7 @@ import eu.kanade.tachiyomi.util.preference.preferenceCategory import eu.kanade.tachiyomi.util.preference.switchPreference import eu.kanade.tachiyomi.util.preference.titleRes import eu.kanade.tachiyomi.util.system.DeviceUtil +import eu.kanade.tachiyomi.util.system.isDynamicColorAvailable import eu.kanade.tachiyomi.util.system.isTablet import eu.kanade.tachiyomi.widget.preference.ThemesPreference import java.util.Date diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt index cb6b12483f..3c3e4b8470 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt @@ -24,10 +24,8 @@ import android.util.TypedValue import android.view.Display import android.view.View import android.view.WindowManager -import android.widget.Toast import androidx.annotation.AttrRes import androidx.annotation.ColorInt -import androidx.annotation.StringRes import androidx.appcompat.view.ContextThemeWrapper import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat @@ -52,29 +50,6 @@ import kotlin.math.roundToInt private const val TABLET_UI_MIN_SCREEN_WIDTH_DP = 720 -/** - * Display a toast in this context. - * - * @param resource the text resource. - * @param duration the duration of the toast. Defaults to short. - */ -fun Context.toast(@StringRes resource: Int, duration: Int = Toast.LENGTH_SHORT, block: (Toast) -> Unit = {}): Toast { - return toast(getString(resource), duration, block) -} - -/** - * Display a toast in this context. - * - * @param text the text to display. - * @param duration the duration of the toast. Defaults to short. - */ -fun Context.toast(text: String?, duration: Int = Toast.LENGTH_SHORT, block: (Toast) -> Unit = {}): Toast { - return Toast.makeText(applicationContext, text.orEmpty(), duration).also { - block(it) - it.show() - } -} - /** * Copies a string to clipboard * diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtilExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtilExtensions.kt new file mode 100644 index 0000000000..396ba3fd7f --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtilExtensions.kt @@ -0,0 +1,8 @@ +package eu.kanade.tachiyomi.util.system + +import android.os.Build +import com.google.android.material.color.DynamicColors + +val DeviceUtil.isDynamicColorAvailable by lazy { + DynamicColors.isDynamicColorAvailable() || (DeviceUtil.isSamsung && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) +} diff --git a/core/.gitignore b/core/.gitignore new file mode 100644 index 0000000000..42afabfd2a --- /dev/null +++ b/core/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/core/build.gradle.kts b/core/build.gradle.kts new file mode 100644 index 0000000000..1f2696d2bf --- /dev/null +++ b/core/build.gradle.kts @@ -0,0 +1,46 @@ +plugins { + id("com.android.library") + kotlin("android") + kotlin("plugin.serialization") +} + +android { + namespace = "eu.kanade.tachiyomi.core" + compileSdk = AndroidConfig.compileSdk + + defaultConfig { + minSdk = AndroidConfig.minSdk + targetSdk = AndroidConfig.targetSdk + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_1_8.toString() + } +} + +dependencies { + implementation(project(":i18n")) + + api(libs.logcat) + + api(libs.rxjava) + + api(libs.okhttp.core) + api(libs.okhttp.logging) + api(libs.okhttp.dnsoverhttps) + api(libs.okio) + + api(kotlinx.coroutines.core) + api(kotlinx.serialization.json) + + api(libs.injekt.core) + + api(libs.preferencektx) + + implementation(androidx.corektx) +} diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..568741e54f --- /dev/null +++ b/core/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/AndroidCookieJar.kt b/core/src/main/java/eu/kanade/tachiyomi/network/AndroidCookieJar.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/network/AndroidCookieJar.kt rename to core/src/main/java/eu/kanade/tachiyomi/network/AndroidCookieJar.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/DohProviders.kt b/core/src/main/java/eu/kanade/tachiyomi/network/DohProviders.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/network/DohProviders.kt rename to core/src/main/java/eu/kanade/tachiyomi/network/DohProviders.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt b/core/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt similarity index 85% rename from app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt rename to core/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt index 4141249c1a..84b4039534 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt +++ b/core/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt @@ -1,20 +1,20 @@ package eu.kanade.tachiyomi.network import android.content.Context -import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import androidx.preference.PreferenceManager import eu.kanade.tachiyomi.network.interceptor.CloudflareInterceptor import eu.kanade.tachiyomi.network.interceptor.Http103Interceptor import eu.kanade.tachiyomi.network.interceptor.UserAgentInterceptor import okhttp3.Cache import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor -import uy.kohesive.injekt.injectLazy import java.io.File import java.util.concurrent.TimeUnit class NetworkHelper(context: Context) { - private val preferences: PreferencesHelper by injectLazy() + // TODO: Abstract preferences similar to 1.x + private val preferences = PreferenceManager.getDefaultSharedPreferences(context) private val cacheDir = File(context.cacheDir, "network_cache") private val cacheSize = 5L * 1024 * 1024 // 5 MiB @@ -36,14 +36,14 @@ class NetworkHelper(context: Context) { .addInterceptor(userAgentInterceptor) .addNetworkInterceptor(http103Interceptor) - if (preferences.verboseLogging()) { + if (preferences.getBoolean("verbose_logging", false)) { val httpLoggingInterceptor = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.HEADERS } builder.addNetworkInterceptor(httpLoggingInterceptor) } - when (preferences.dohProvider()) { + when (preferences.getInt("doh_provider", -1)) { PREF_DOH_CLOUDFLARE -> builder.dohCloudflare() PREF_DOH_GOOGLE -> builder.dohGoogle() PREF_DOH_ADGUARD -> builder.dohAdGuard() @@ -70,6 +70,6 @@ class NetworkHelper(context: Context) { } val defaultUserAgent by lazy { - preferences.defaultUserAgent().get() + preferences.getString("default_user_agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:104.0) Gecko/20100101 Firefox/104.0")!! } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/OkHttpExtensions.kt b/core/src/main/java/eu/kanade/tachiyomi/network/OkHttpExtensions.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/network/OkHttpExtensions.kt rename to core/src/main/java/eu/kanade/tachiyomi/network/OkHttpExtensions.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/ProgressListener.kt b/core/src/main/java/eu/kanade/tachiyomi/network/ProgressListener.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/network/ProgressListener.kt rename to core/src/main/java/eu/kanade/tachiyomi/network/ProgressListener.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/ProgressResponseBody.kt b/core/src/main/java/eu/kanade/tachiyomi/network/ProgressResponseBody.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/network/ProgressResponseBody.kt rename to core/src/main/java/eu/kanade/tachiyomi/network/ProgressResponseBody.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/Requests.kt b/core/src/main/java/eu/kanade/tachiyomi/network/Requests.kt similarity index 95% rename from app/src/main/java/eu/kanade/tachiyomi/network/Requests.kt rename to core/src/main/java/eu/kanade/tachiyomi/network/Requests.kt index 694f7f47e9..082543dc44 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/network/Requests.kt +++ b/core/src/main/java/eu/kanade/tachiyomi/network/Requests.kt @@ -10,7 +10,7 @@ import java.util.concurrent.TimeUnit.MINUTES private val DEFAULT_CACHE_CONTROL = CacheControl.Builder().maxAge(10, MINUTES).build() private val DEFAULT_HEADERS = Headers.Builder().build() private val DEFAULT_BODY: RequestBody = FormBody.Builder().build() -internal val CACHE_CONTROL_NO_STORE = CacheControl.Builder().noStore().build() +val CACHE_CONTROL_NO_STORE = CacheControl.Builder().noStore().build() fun GET( url: String, diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt b/core/src/main/java/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt similarity index 99% rename from app/src/main/java/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt rename to core/src/main/java/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt index 683732a743..b467beac0f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt +++ b/core/src/main/java/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt @@ -5,7 +5,7 @@ import android.content.Context import android.webkit.WebView import android.widget.Toast import androidx.core.content.ContextCompat -import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.core.R import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.util.system.WebViewClientCompat import eu.kanade.tachiyomi.util.system.isOutdated diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/interceptor/Http103Interceptor.kt b/core/src/main/java/eu/kanade/tachiyomi/network/interceptor/Http103Interceptor.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/network/interceptor/Http103Interceptor.kt rename to core/src/main/java/eu/kanade/tachiyomi/network/interceptor/Http103Interceptor.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/interceptor/RateLimitInterceptor.kt b/core/src/main/java/eu/kanade/tachiyomi/network/interceptor/RateLimitInterceptor.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/network/interceptor/RateLimitInterceptor.kt rename to core/src/main/java/eu/kanade/tachiyomi/network/interceptor/RateLimitInterceptor.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/interceptor/SpecificHostRateLimitInterceptor.kt b/core/src/main/java/eu/kanade/tachiyomi/network/interceptor/SpecificHostRateLimitInterceptor.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/network/interceptor/SpecificHostRateLimitInterceptor.kt rename to core/src/main/java/eu/kanade/tachiyomi/network/interceptor/SpecificHostRateLimitInterceptor.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/interceptor/UserAgentInterceptor.kt b/core/src/main/java/eu/kanade/tachiyomi/network/interceptor/UserAgentInterceptor.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/network/interceptor/UserAgentInterceptor.kt rename to core/src/main/java/eu/kanade/tachiyomi/network/interceptor/UserAgentInterceptor.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/interceptor/WebViewInterceptor.kt b/core/src/main/java/eu/kanade/tachiyomi/network/interceptor/WebViewInterceptor.kt similarity index 98% rename from app/src/main/java/eu/kanade/tachiyomi/network/interceptor/WebViewInterceptor.kt rename to core/src/main/java/eu/kanade/tachiyomi/network/interceptor/WebViewInterceptor.kt index 4955c47f58..13e6bdb519 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/network/interceptor/WebViewInterceptor.kt +++ b/core/src/main/java/eu/kanade/tachiyomi/network/interceptor/WebViewInterceptor.kt @@ -5,7 +5,7 @@ import android.os.Build import android.webkit.WebSettings import android.webkit.WebView import android.widget.Toast -import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.core.R import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.system.DeviceUtil diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/lang/CoroutinesExtensions.kt b/core/src/main/java/eu/kanade/tachiyomi/util/lang/CoroutinesExtensions.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/util/lang/CoroutinesExtensions.kt rename to core/src/main/java/eu/kanade/tachiyomi/util/lang/CoroutinesExtensions.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/lang/RxCoroutineBridge.kt b/core/src/main/java/eu/kanade/tachiyomi/util/lang/RxCoroutineBridge.kt similarity index 97% rename from app/src/main/java/eu/kanade/tachiyomi/util/lang/RxCoroutineBridge.kt rename to core/src/main/java/eu/kanade/tachiyomi/util/lang/RxCoroutineBridge.kt index ceef8a2e8f..73dc7c89bc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/lang/RxCoroutineBridge.kt +++ b/core/src/main/java/eu/kanade/tachiyomi/util/lang/RxCoroutineBridge.kt @@ -5,6 +5,7 @@ import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.InternalCoroutinesApi import kotlinx.coroutines.launch import kotlinx.coroutines.suspendCancellableCoroutine import rx.Emitter @@ -20,6 +21,7 @@ import kotlin.coroutines.resumeWithException suspend fun Observable.awaitSingle(): T = single().awaitOne() +@OptIn(InternalCoroutinesApi::class) private suspend fun Observable.awaitOne(): T = suspendCancellableCoroutine { cont -> cont.unsubscribeOnCancellation( subscribe( diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtil.kt b/core/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtil.kt similarity index 86% rename from app/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtil.kt rename to core/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtil.kt index 3da54c1eba..def364682d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtil.kt +++ b/core/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtil.kt @@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.util.system import android.annotation.SuppressLint import android.os.Build -import com.google.android.material.color.DynamicColors import logcat.LogPriority object DeviceUtil { @@ -31,10 +30,6 @@ object DeviceUtil { Build.MANUFACTURER.equals("samsung", ignoreCase = true) } - val isDynamicColorAvailable by lazy { - DynamicColors.isDynamicColorAvailable() || (isSamsung && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) - } - val invalidDefaultBrowsers = listOf("android", "com.huawei.android.internal.app") @SuppressLint("PrivateApi") diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/LogcatExtensions.kt b/core/src/main/java/eu/kanade/tachiyomi/util/system/LogcatExtensions.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/util/system/LogcatExtensions.kt rename to core/src/main/java/eu/kanade/tachiyomi/util/system/LogcatExtensions.kt diff --git a/core/src/main/java/eu/kanade/tachiyomi/util/system/ToastExtensions.kt b/core/src/main/java/eu/kanade/tachiyomi/util/system/ToastExtensions.kt new file mode 100644 index 0000000000..4901e7463a --- /dev/null +++ b/core/src/main/java/eu/kanade/tachiyomi/util/system/ToastExtensions.kt @@ -0,0 +1,28 @@ +package eu.kanade.tachiyomi.util.system + +import android.content.Context +import android.widget.Toast +import androidx.annotation.StringRes + +/** + * Display a toast in this context. + * + * @param resource the text resource. + * @param duration the duration of the toast. Defaults to short. + */ +fun Context.toast(@StringRes resource: Int, duration: Int = Toast.LENGTH_SHORT, block: (Toast) -> Unit = {}): Toast { + return toast(getString(resource), duration, block) +} + +/** + * Display a toast in this context. + * + * @param text the text to display. + * @param duration the duration of the toast. Defaults to short. + */ +fun Context.toast(text: String?, duration: Int = Toast.LENGTH_SHORT, block: (Toast) -> Unit = {}): Toast { + return Toast.makeText(applicationContext, text.orEmpty(), duration).also { + block(it) + it.show() + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/WebViewClientCompat.kt b/core/src/main/java/eu/kanade/tachiyomi/util/system/WebViewClientCompat.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/util/system/WebViewClientCompat.kt rename to core/src/main/java/eu/kanade/tachiyomi/util/system/WebViewClientCompat.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/WebViewUtil.kt b/core/src/main/java/eu/kanade/tachiyomi/util/system/WebViewUtil.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/util/system/WebViewUtil.kt rename to core/src/main/java/eu/kanade/tachiyomi/util/system/WebViewUtil.kt diff --git a/settings.gradle.kts b/settings.gradle.kts index 4e928658bc..62c805b78f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -37,3 +37,5 @@ dependencyResolutionManagement { rootProject.name = "Tachiyomi" include(":app") include(":i18n") +include(":source-api") +include(":core") diff --git a/source-api/.gitignore b/source-api/.gitignore new file mode 100644 index 0000000000..42afabfd2a --- /dev/null +++ b/source-api/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/source-api/build.gradle.kts b/source-api/build.gradle.kts new file mode 100644 index 0000000000..21e5b2951b --- /dev/null +++ b/source-api/build.gradle.kts @@ -0,0 +1,39 @@ +plugins { + id("com.android.library") + kotlin("android") + kotlin("plugin.serialization") +} + +android { + namespace = "eu.kanade.tachiyomi.source" + compileSdk = AndroidConfig.compileSdk + + defaultConfig { + minSdk = AndroidConfig.minSdk + targetSdk = AndroidConfig.targetSdk + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_1_8.toString() + } +} + +dependencies { + + implementation(project(":core")) + + api(kotlinx.serialization.json) + + api(libs.rxjava) + + api(libs.preferencektx) + + api(libs.jsoup) + + implementation(androidx.corektx) +} diff --git a/source-api/src/main/AndroidManifest.xml b/source-api/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..568741e54f --- /dev/null +++ b/source-api/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/CatalogueSource.kt b/source-api/src/main/java/eu/kanade/tachiyomi/source/CatalogueSource.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/source/CatalogueSource.kt rename to source-api/src/main/java/eu/kanade/tachiyomi/source/CatalogueSource.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/ConfigurableSource.kt b/source-api/src/main/java/eu/kanade/tachiyomi/source/ConfigurableSource.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/source/ConfigurableSource.kt rename to source-api/src/main/java/eu/kanade/tachiyomi/source/ConfigurableSource.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/Source.kt b/source-api/src/main/java/eu/kanade/tachiyomi/source/Source.kt similarity index 64% rename from app/src/main/java/eu/kanade/tachiyomi/source/Source.kt rename to source-api/src/main/java/eu/kanade/tachiyomi/source/Source.kt index fe5e1019fc..32dccbb735 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/Source.kt +++ b/source-api/src/main/java/eu/kanade/tachiyomi/source/Source.kt @@ -1,16 +1,10 @@ package eu.kanade.tachiyomi.source -import android.graphics.drawable.Drawable -import eu.kanade.domain.source.model.SourceData -import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.extension.ExtensionManager 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.util.lang.awaitSingle import rx.Observable -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get /** * A basic interface for creating a source. It could be an online source, a local source, etc... @@ -88,26 +82,3 @@ interface Source { return fetchPageList(chapter).awaitSingle() } } - -fun Source.icon(): Drawable? = Injekt.get().getAppIconForSource(this) - -fun Source.getPreferenceKey(): String = "source_$id" - -fun Source.toSourceData(): SourceData = SourceData(id = id, lang = lang, name = name) - -fun Source.getNameForMangaInfo(): String { - val preferences = Injekt.get() - val enabledLanguages = preferences.enabledLanguages().get() - .filterNot { it in listOf("all", "other") } - val hasOneActiveLanguages = enabledLanguages.size == 1 - val isInEnabledLanguages = lang in enabledLanguages - return when { - // For edge cases where user disables a source they got manga of in their library. - hasOneActiveLanguages && !isInEnabledLanguages -> toString() - // Hide the language tag when only one language is used. - hasOneActiveLanguages && isInEnabledLanguages -> name - else -> toString() - } -} - -fun Source.isLocalOrStub(): Boolean = id == LocalSource.ID || this is SourceManager.StubSource diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/SourceFactory.kt b/source-api/src/main/java/eu/kanade/tachiyomi/source/SourceFactory.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/source/SourceFactory.kt rename to source-api/src/main/java/eu/kanade/tachiyomi/source/SourceFactory.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/UnmeteredSource.kt b/source-api/src/main/java/eu/kanade/tachiyomi/source/UnmeteredSource.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/source/UnmeteredSource.kt rename to source-api/src/main/java/eu/kanade/tachiyomi/source/UnmeteredSource.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/model/Filter.kt b/source-api/src/main/java/eu/kanade/tachiyomi/source/model/Filter.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/source/model/Filter.kt rename to source-api/src/main/java/eu/kanade/tachiyomi/source/model/Filter.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/model/FilterList.kt b/source-api/src/main/java/eu/kanade/tachiyomi/source/model/FilterList.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/source/model/FilterList.kt rename to source-api/src/main/java/eu/kanade/tachiyomi/source/model/FilterList.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/model/MangasPage.kt b/source-api/src/main/java/eu/kanade/tachiyomi/source/model/MangasPage.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/source/model/MangasPage.kt rename to source-api/src/main/java/eu/kanade/tachiyomi/source/model/MangasPage.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/model/Page.kt b/source-api/src/main/java/eu/kanade/tachiyomi/source/model/Page.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/source/model/Page.kt rename to source-api/src/main/java/eu/kanade/tachiyomi/source/model/Page.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/model/SChapter.kt b/source-api/src/main/java/eu/kanade/tachiyomi/source/model/SChapter.kt similarity index 70% rename from app/src/main/java/eu/kanade/tachiyomi/source/model/SChapter.kt rename to source-api/src/main/java/eu/kanade/tachiyomi/source/model/SChapter.kt index 572d7020e0..f53bbe8f0a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/model/SChapter.kt +++ b/source-api/src/main/java/eu/kanade/tachiyomi/source/model/SChapter.kt @@ -1,6 +1,5 @@ package eu.kanade.tachiyomi.source.model -import data.Chapters import java.io.Serializable interface SChapter : Serializable { @@ -23,14 +22,6 @@ interface SChapter : Serializable { scanlator = other.scanlator } - fun copyFrom(other: Chapters) { - name = other.name - url = other.url - date_upload = other.date_upload - chapter_number = other.chapter_number - scanlator = other.scanlator - } - companion object { fun create(): SChapter { return SChapterImpl() diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/model/SChapterImpl.kt b/source-api/src/main/java/eu/kanade/tachiyomi/source/model/SChapterImpl.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/source/model/SChapterImpl.kt rename to source-api/src/main/java/eu/kanade/tachiyomi/source/model/SChapterImpl.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/model/SManga.kt b/source-api/src/main/java/eu/kanade/tachiyomi/source/model/SManga.kt similarity index 72% rename from app/src/main/java/eu/kanade/tachiyomi/source/model/SManga.kt rename to source-api/src/main/java/eu/kanade/tachiyomi/source/model/SManga.kt index 824e0e2cac..fb1fab4744 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/model/SManga.kt +++ b/source-api/src/main/java/eu/kanade/tachiyomi/source/model/SManga.kt @@ -1,6 +1,5 @@ package eu.kanade.tachiyomi.source.model -import data.Mangas import java.io.Serializable interface SManga : Serializable { @@ -56,34 +55,6 @@ interface SManga : Serializable { } } - fun copyFrom(other: Mangas) { - if (other.author != null) { - author = other.author - } - - if (other.artist != null) { - artist = other.artist - } - - if (other.description != null) { - description = other.description - } - - if (other.genre != null) { - genre = other.genre.joinToString(separator = ", ") - } - - if (other.thumbnail_url != null) { - thumbnail_url = other.thumbnail_url - } - - status = other.status.toInt() - - if (!initialized) { - initialized = other.initialized - } - } - fun copy() = create().also { it.url = url it.title = title diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/model/SMangaImpl.kt b/source-api/src/main/java/eu/kanade/tachiyomi/source/model/SMangaImpl.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/source/model/SMangaImpl.kt rename to source-api/src/main/java/eu/kanade/tachiyomi/source/model/SMangaImpl.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/HttpSource.kt b/source-api/src/main/java/eu/kanade/tachiyomi/source/online/HttpSource.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/source/online/HttpSource.kt rename to source-api/src/main/java/eu/kanade/tachiyomi/source/online/HttpSource.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/HttpSourceFetcher.kt b/source-api/src/main/java/eu/kanade/tachiyomi/source/online/HttpSourceFetcher.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/source/online/HttpSourceFetcher.kt rename to source-api/src/main/java/eu/kanade/tachiyomi/source/online/HttpSourceFetcher.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/ParsedHttpSource.kt b/source-api/src/main/java/eu/kanade/tachiyomi/source/online/ParsedHttpSource.kt similarity index 99% rename from app/src/main/java/eu/kanade/tachiyomi/source/online/ParsedHttpSource.kt rename to source-api/src/main/java/eu/kanade/tachiyomi/source/online/ParsedHttpSource.kt index 941a3167a8..34376f847e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/ParsedHttpSource.kt +++ b/source-api/src/main/java/eu/kanade/tachiyomi/source/online/ParsedHttpSource.kt @@ -12,6 +12,7 @@ import org.jsoup.nodes.Element /** * A simple implementation for sources from a website using Jsoup, an HTML parser. */ +@Suppress("unused") abstract class ParsedHttpSource : HttpSource() { /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/JsoupExtensions.kt b/source-api/src/main/java/eu/kanade/tachiyomi/util/JsoupExtensions.kt similarity index 100% rename from app/src/main/java/eu/kanade/tachiyomi/util/JsoupExtensions.kt rename to source-api/src/main/java/eu/kanade/tachiyomi/util/JsoupExtensions.kt