From fd3c83cb137afc5f5b1262aacaa9a01f51d2d12f Mon Sep 17 00:00:00 2001 From: Koitharu Date: Mon, 6 Feb 2023 19:45:55 +0200 Subject: [PATCH] Allow to use own UserAgent for each manga source --- app/build.gradle | 2 +- .../bookmarks/ui/adapter/BookmarkListAD.kt | 2 +- .../bookmarks/ui/adapter/BookmarksGroupAD.kt | 8 +++-- .../browser/cloudflare/CloudFlareDialog.kt | 10 ++++-- .../org/koitharu/kotatsu/core/AppModule.kt | 3 +- .../CloudFlareProtectedException.kt | 6 ++-- .../exceptions/resolve/ExceptionResolver.kt | 7 ++-- .../core/network/CloudFlareInterceptor.kt | 10 ++++-- .../core/network/UserAgentInterceptor.kt | 32 ++++++++++++++----- .../kotatsu/core/os/ShortcutsUpdater.kt | 1 + .../core/parser/RemoteMangaRepository.kt | 4 +++ .../core/parser/favicon/FaviconFetcher.kt | 7 ++-- .../kotatsu/details/ui/DetailsFragment.kt | 7 +++- .../details/ui/scrobbling/ScrobblingInfoAD.kt | 2 +- .../scrobbling/ScrobblingInfoBottomSheet.kt | 4 +-- .../download/domain/DownloadManager.kt | 15 +++++++-- .../kotatsu/download/ui/DownloadItemAD.kt | 14 ++++++-- .../ui/adapter/ExploreAdapterDelegates.kt | 2 +- .../ui/categories/adapter/CategoryAD.kt | 10 ++++-- .../kotatsu/image/ui/ImageActivity.kt | 9 ++++-- .../kotatsu/list/ui/MangaListFragment.kt | 2 +- .../list/ui/adapter/MangaGridItemAD.kt | 2 +- .../ui/adapter/MangaListDetailedItemAD.kt | 2 +- .../list/ui/adapter/MangaListItemAD.kt | 8 +++-- .../kotatsu/list/ui/model/MangaItemModel.kt | 6 +++- .../kotatsu/local/ui/ImportService.kt | 6 +++- .../kotatsu/reader/domain/PageLoader.kt | 1 + .../colorfilter/ColorFilterConfigActivity.kt | 12 +++++-- .../ui/thumbnails/adapter/PageThumbnailAD.kt | 9 ++++-- .../adapter/SearchSuggestionSourceAD.kt | 6 ++-- .../adapter/SearchSuggestionsMangaListAD.kt | 2 +- .../adapter/SourceConfigAdapterDelegates.kt | 14 ++++---- .../sources/auth/SourceAuthActivity.kt | 10 +++--- .../tracker/ui/feed/adapter/FeedItemAD.kt | 2 +- .../kotatsu/tracker/work/TrackWorker.kt | 6 +++- .../org/koitharu/kotatsu/utils/ext/CoilExt.kt | 5 ++- .../widget/recent/RecentListFactory.kt | 1 + .../kotatsu/widget/shelf/ShelfListFactory.kt | 1 + 38 files changed, 181 insertions(+), 69 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 2fea65e6f..24559e2ff 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -86,7 +86,7 @@ afterEvaluate { } } dependencies { - implementation('com.github.KotatsuApp:kotatsu-parsers:c28e2a72d5') { + implementation('com.github.KotatsuApp:kotatsu-parsers:00abaea324') { exclude group: 'org.json', module: 'json' } diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkListAD.kt b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkListAD.kt index 79ce1e06b..6b3c383f4 100644 --- a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkListAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkListAD.kt @@ -26,7 +26,7 @@ fun bookmarkListAD( binding.root.setOnLongClickListener(listener) bind { - binding.imageViewThumb.newImageRequest(item.imageUrl)?.run { + binding.imageViewThumb.newImageRequest(item.imageUrl, item.manga.source)?.run { referer(item.manga.publicUrl) placeholder(R.drawable.ic_placeholder) fallback(R.drawable.ic_placeholder) diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAD.kt b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAD.kt index 7927ed287..c3beeb87b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAD.kt @@ -14,7 +14,11 @@ import org.koitharu.kotatsu.bookmarks.ui.model.BookmarksGroup import org.koitharu.kotatsu.databinding.ItemBookmarksGroupBinding import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.utils.ext.* +import org.koitharu.kotatsu.utils.ext.clearItemDecorations +import org.koitharu.kotatsu.utils.ext.disposeImageRequest +import org.koitharu.kotatsu.utils.ext.enqueueWith +import org.koitharu.kotatsu.utils.ext.newImageRequest +import org.koitharu.kotatsu.utils.ext.referer fun bookmarksGroupAD( coil: ImageLoader, @@ -45,7 +49,7 @@ fun bookmarksGroupAD( binding.recyclerView.addItemDecoration(spacingDecoration) selectionController.attachToRecyclerView(item.manga, binding.recyclerView) } - binding.imageViewCover.newImageRequest(item.manga.coverUrl)?.run { + binding.imageViewCover.newImageRequest(item.manga.coverUrl, item.manga.source)?.run { referer(item.manga.publicUrl) placeholder(R.drawable.ic_placeholder) fallback(R.drawable.ic_placeholder) diff --git a/app/src/main/java/org/koitharu/kotatsu/browser/cloudflare/CloudFlareDialog.kt b/app/src/main/java/org/koitharu/kotatsu/browser/cloudflare/CloudFlareDialog.kt index b95eeac99..2b4ed813c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/browser/cloudflare/CloudFlareDialog.kt +++ b/app/src/main/java/org/koitharu/kotatsu/browser/cloudflare/CloudFlareDialog.kt @@ -12,7 +12,9 @@ import androidx.core.view.isInvisible import androidx.fragment.app.setFragmentResult import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint +import okhttp3.Headers import org.koitharu.kotatsu.base.ui.AlertDialogFragment +import org.koitharu.kotatsu.core.network.CommonHeaders import org.koitharu.kotatsu.core.network.UserAgentInterceptor import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar import org.koitharu.kotatsu.databinding.FragmentCloudflareBinding @@ -42,7 +44,7 @@ class CloudFlareDialog : AlertDialogFragment(), Cloud cacheMode = WebSettings.LOAD_DEFAULT domStorageEnabled = true databaseEnabled = true - userAgentString = UserAgentInterceptor.userAgentChrome + userAgentString = arguments?.getString(ARG_UA) ?: UserAgentInterceptor.userAgentChrome } binding.webView.webViewClient = CloudFlareClient(cookieJar, this, url.orEmpty()) CookieManager.getInstance().setAcceptThirdPartyCookies(binding.webView, true) @@ -92,9 +94,13 @@ class CloudFlareDialog : AlertDialogFragment(), Cloud const val TAG = "CloudFlareDialog" const val EXTRA_RESULT = "result" private const val ARG_URL = "url" + private const val ARG_UA = "ua" - fun newInstance(url: String) = CloudFlareDialog().withArgs(1) { + fun newInstance(url: String, headers: Headers?) = CloudFlareDialog().withArgs(2) { putString(ARG_URL, url) + headers?.get(CommonHeaders.USER_AGENT)?.let { + putString(ARG_UA, it) + } } } } diff --git a/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt b/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt index bf4c98354..968731bce 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt @@ -85,6 +85,7 @@ interface AppModule { @Singleton fun provideOkHttpClient( localStorageManager: LocalStorageManager, + userAgentInterceptor: UserAgentInterceptor, cookieJar: CookieJar, settings: AppSettings, ): OkHttpClient { @@ -97,7 +98,7 @@ interface AppModule { dns(DoHManager(cache, settings)) cache(cache) addInterceptor(GZipInterceptor()) - addInterceptor(UserAgentInterceptor()) + addInterceptor(userAgentInterceptor) addInterceptor(CloudFlareInterceptor()) if (BuildConfig.DEBUG) { addInterceptor(CurlLoggingInterceptor()) diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/CloudFlareProtectedException.kt b/app/src/main/java/org/koitharu/kotatsu/core/exceptions/CloudFlareProtectedException.kt index ef20b4fb0..ee6163e25 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/CloudFlareProtectedException.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/exceptions/CloudFlareProtectedException.kt @@ -1,7 +1,9 @@ package org.koitharu.kotatsu.core.exceptions +import okhttp3.Headers import okio.IOException class CloudFlareProtectedException( - val url: String -) : IOException("Protected by CloudFlare") \ No newline at end of file + val url: String, + val headers: Headers, +) : IOException("Protected by CloudFlare") diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/ExceptionResolver.kt b/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/ExceptionResolver.kt index b7147aadd..4afa01e5d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/ExceptionResolver.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/ExceptionResolver.kt @@ -7,6 +7,7 @@ import androidx.collection.ArrayMap import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity import kotlinx.coroutines.suspendCancellableCoroutine +import okhttp3.Headers import org.koitharu.kotatsu.R import org.koitharu.kotatsu.browser.BrowserActivity import org.koitharu.kotatsu.browser.cloudflare.CloudFlareDialog @@ -43,7 +44,7 @@ class ExceptionResolver private constructor( } suspend fun resolve(e: Throwable): Boolean = when (e) { - is CloudFlareProtectedException -> resolveCF(e.url) + is CloudFlareProtectedException -> resolveCF(e.url, e.headers) is AuthRequiredException -> resolveAuthException(e.source) is NotFoundException -> { openInBrowser(e.url) @@ -53,8 +54,8 @@ class ExceptionResolver private constructor( else -> false } - private suspend fun resolveCF(url: String): Boolean { - val dialog = CloudFlareDialog.newInstance(url) + private suspend fun resolveCF(url: String, headers: Headers): Boolean { + val dialog = CloudFlareDialog.newInstance(url, headers) val fm = getFragmentManager() return suspendCancellableCoroutine { cont -> fm.clearFragmentResult(CloudFlareDialog.TAG) diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/CloudFlareInterceptor.kt b/app/src/main/java/org/koitharu/kotatsu/core/network/CloudFlareInterceptor.kt index a32a94c83..b4dcc9e62 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/network/CloudFlareInterceptor.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/network/CloudFlareInterceptor.kt @@ -13,13 +13,17 @@ private const val SERVER_CLOUDFLARE = "cloudflare" class CloudFlareInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { - val response = chain.proceed(chain.request()) + val request = chain.request() + val response = chain.proceed(request) if (response.code == HTTP_FORBIDDEN || response.code == HTTP_UNAVAILABLE) { if (response.header(HEADER_SERVER)?.startsWith(SERVER_CLOUDFLARE) == true) { response.closeQuietly() - throw CloudFlareProtectedException(response.request.url.toString()) + throw CloudFlareProtectedException( + url = response.request.url.toString(), + headers = request.headers, + ) } } return response } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/UserAgentInterceptor.kt b/app/src/main/java/org/koitharu/kotatsu/core/network/UserAgentInterceptor.kt index 6a781fd45..a0b46d309 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/network/UserAgentInterceptor.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/network/UserAgentInterceptor.kt @@ -1,24 +1,40 @@ package org.koitharu.kotatsu.core.network import android.os.Build -import java.util.* +import dagger.Lazy import okhttp3.Interceptor +import okhttp3.Request import okhttp3.Response import org.koitharu.kotatsu.BuildConfig +import org.koitharu.kotatsu.core.parser.MangaRepository +import org.koitharu.kotatsu.core.parser.RemoteMangaRepository +import org.koitharu.kotatsu.parsers.model.MangaSource +import java.util.Locale +import javax.inject.Inject +import javax.inject.Singleton -class UserAgentInterceptor : Interceptor { +@Singleton +class UserAgentInterceptor @Inject constructor( + private val mangaRepositoryFactoryLazy: Lazy, +) : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val request = chain.request() return chain.proceed( if (request.header(CommonHeaders.USER_AGENT) == null) { request.newBuilder() - .addHeader(CommonHeaders.USER_AGENT, userAgentChrome) + .addHeader(CommonHeaders.USER_AGENT, getUserAgent(request)) .build() - } else request + } else request, ) } + private fun getUserAgent(request: Request): String { + val source = request.tag(MangaSource::class.java) ?: return userAgent + val repository = mangaRepositoryFactoryLazy.get().create(source) as? RemoteMangaRepository + return repository?.userAgent ?: userAgent + } + companion object { val userAgent @@ -28,7 +44,7 @@ class UserAgentInterceptor : Interceptor { Build.MODEL, Build.BRAND, Build.DEVICE, - Locale.getDefault().language + Locale.getDefault().language, ) // TODO Decide what to do with this afterwards val userAgentChrome @@ -36,8 +52,8 @@ class UserAgentInterceptor : Interceptor { "Mozilla/5.0 (Linux; Android %s; %s) AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/100.0.4896.127 Mobile Safari/537.36" ).format( - Build.VERSION.RELEASE, - Build.MODEL, - ) + Build.VERSION.RELEASE, + Build.MODEL, + ) } } diff --git a/app/src/main/java/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt b/app/src/main/java/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt index 82d7fa4bb..39708b1bd 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt @@ -118,6 +118,7 @@ class ShortcutsUpdater @Inject constructor( ImageRequest.Builder(context) .data(manga.coverUrl) .size(iconSize.width, iconSize.height) + .tag(manga.source) .precision(Precision.EXACT) .scale(Scale.FILL) .build(), diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt index ecd2d170f..ba4da8fa9 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt @@ -8,6 +8,7 @@ import kotlinx.coroutines.async import kotlinx.coroutines.currentCoroutineContext import org.koitharu.kotatsu.core.cache.ContentCache import org.koitharu.kotatsu.core.cache.SafeDeferred +import org.koitharu.kotatsu.core.network.CommonHeaders import org.koitharu.kotatsu.core.prefs.SourceSettings import org.koitharu.kotatsu.parsers.MangaParser import org.koitharu.kotatsu.parsers.MangaParserAuthProvider @@ -39,6 +40,9 @@ class RemoteMangaRepository( getConfig().defaultSortOrder = value } + val userAgent: String? + get() = parser.headers?.get(CommonHeaders.USER_AGENT) + override suspend fun getList(offset: Int, query: String): List { return parser.getList(offset, query) } diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/favicon/FaviconFetcher.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/favicon/FaviconFetcher.kt index ee052cfdd..0fdd23162 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/parser/favicon/FaviconFetcher.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/favicon/FaviconFetcher.kt @@ -53,7 +53,7 @@ class FaviconFetcher( options.size.height.pxOrElse { FALLBACK_SIZE }, ) val icon = checkNotNull(favicons.find(sizePx)) { "No favicons found" } - val response = loadIcon(icon.url, favicons.referer) + val response = loadIcon(icon.url, repo.userAgent, favicons.referer) val responseBody = response.requireBody() val source = writeToDiskCache(responseBody)?.toImageSource() ?: responseBody.toImageSource() return SourceResult( @@ -63,11 +63,14 @@ class FaviconFetcher( ) } - private suspend fun loadIcon(url: String, referer: String): Response { + private suspend fun loadIcon(url: String, userAgent: String?, referer: String): Response { val request = Request.Builder() .url(url) .get() .header(CommonHeaders.REFERER, referer) + if (userAgent != null) { + request.header(CommonHeaders.USER_AGENT, userAgent) + } @Suppress("UNCHECKED_CAST") options.tags.asMap().forEach { request.tag(it.key as Class, it.value) } val response = okHttpClient.newCall(request.build()).await() diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt index 6d2203632..5211d9320 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt @@ -254,7 +254,11 @@ class DetailsFragment : R.id.imageView_cover -> { startActivity( - ImageActivity.newIntent(v.context, manga.largeCoverUrl.ifNullOrEmpty { manga.coverUrl }), + ImageActivity.newIntent( + v.context, + manga.largeCoverUrl.ifNullOrEmpty { manga.coverUrl }, + manga.source, + ), scaleUpActivityOptionsOf(v).toBundle(), ) } @@ -337,6 +341,7 @@ class DetailsFragment : .target(binding.imageViewCover) .size(CoverSizeResolver(binding.imageViewCover)) .data(imageUrl) + .tag(manga.source) .crossfade(context) .referer(manga.publicUrl) .lifecycle(viewLifecycleOwner) diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoAD.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoAD.kt index 7c3af4dc8..848e73361 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoAD.kt @@ -23,7 +23,7 @@ fun scrobblingInfoAD( } bind { - binding.imageViewCover.newImageRequest(item.coverUrl)?.run { + binding.imageViewCover.newImageRequest(item.coverUrl /* TODO */, null)?.run { placeholder(R.drawable.ic_placeholder) fallback(R.drawable.ic_placeholder) error(R.drawable.ic_error_placeholder) diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt index 39fd5fd45..c5350923b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt @@ -106,7 +106,7 @@ class ScrobblingInfoBottomSheet : R.id.imageView_cover -> { val coverUrl = viewModel.scrobblingInfo.value?.getOrNull(scrobblerIndex)?.coverUrl ?: return val options = scaleUpActivityOptionsOf(v) - startActivity(ImageActivity.newIntent(v.context, coverUrl), options.toBundle()) + startActivity(ImageActivity.newIntent(v.context, coverUrl, null), options.toBundle()) } } } @@ -123,7 +123,7 @@ class ScrobblingInfoBottomSheet : binding.spinnerStatus.setSelection(scrobbling.status?.ordinal ?: -1) binding.imageViewLogo.contentDescription = getString(scrobbling.scrobbler.titleResId) binding.imageViewLogo.setImageResource(scrobbling.scrobbler.iconResId) - binding.imageViewCover.newImageRequest(scrobbling.coverUrl)?.apply { + binding.imageViewCover.newImageRequest(scrobbling.coverUrl, null)?.apply { lifecycle(viewLifecycleOwner) placeholder(R.drawable.ic_placeholder) fallback(R.drawable.ic_placeholder) diff --git a/app/src/main/java/org/koitharu/kotatsu/download/domain/DownloadManager.kt b/app/src/main/java/org/koitharu/kotatsu/download/domain/DownloadManager.kt index 931d09ae9..e534f9120 100644 --- a/app/src/main/java/org/koitharu/kotatsu/download/domain/DownloadManager.kt +++ b/app/src/main/java/org/koitharu/kotatsu/download/domain/DownloadManager.kt @@ -118,7 +118,7 @@ class DownloadManager @AssistedInject constructor( val data = if (manga.chapters.isNullOrEmpty()) repo.getDetails(manga) else manga output = CbzMangaOutput.get(destination, data) val coverUrl = data.largeCoverUrl ?: data.coverUrl - downloadFile(coverUrl, data.publicUrl, destination, tempFileName).let { file -> + downloadFile(coverUrl, data.publicUrl, destination, tempFileName, repo.source).let { file -> output.addCover(file, MimeTypeMap.getFileExtensionFromUrl(coverUrl)) } val chapters = checkNotNull( @@ -139,7 +139,8 @@ class DownloadManager @AssistedInject constructor( for ((pageIndex, page) in pages.withIndex()) { runFailsafe(outState, pausingHandle) { val url = repo.getPageUrl(page) - val file = cache[url] ?: downloadFile(url, page.referer, destination, tempFileName) + val file = cache[url] + ?: downloadFile(url, page.referer, destination, tempFileName, repo.source) output.addPage( chapter = chapter, file = file, @@ -209,10 +210,17 @@ class DownloadManager @AssistedInject constructor( } } - private suspend fun downloadFile(url: String, referer: String, destination: File, tempFileName: String): File { + private suspend fun downloadFile( + url: String, + referer: String, + destination: File, + tempFileName: String, + source: MangaSource, + ): File { val request = Request.Builder() .url(url) .header(CommonHeaders.REFERER, referer) + .tag(source) .cacheControl(CommonHeaders.CACHE_CONTROL_DISABLED) .get() .build() @@ -243,6 +251,7 @@ class DownloadManager @AssistedInject constructor( ImageRequest.Builder(context) .data(manga.coverUrl) .referer(manga.publicUrl) + .tag(manga.source) .size(coverWidth, coverHeight) .scale(Scale.FILL) .build(), diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/DownloadItemAD.kt b/app/src/main/java/org/koitharu/kotatsu/download/ui/DownloadItemAD.kt index 4d24c9104..81554a088 100644 --- a/app/src/main/java/org/koitharu/kotatsu/download/ui/DownloadItemAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/download/ui/DownloadItemAD.kt @@ -13,7 +13,11 @@ import org.koitharu.kotatsu.databinding.ItemDownloadBinding import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.download.domain.DownloadState import org.koitharu.kotatsu.parsers.util.format -import org.koitharu.kotatsu.utils.ext.* +import org.koitharu.kotatsu.utils.ext.enqueueWith +import org.koitharu.kotatsu.utils.ext.getDisplayMessage +import org.koitharu.kotatsu.utils.ext.newImageRequest +import org.koitharu.kotatsu.utils.ext.onFirst +import org.koitharu.kotatsu.utils.ext.referer fun downloadItemAD( scope: CoroutineScope, @@ -40,7 +44,7 @@ fun downloadItemAD( bind { job?.cancel() job = item.progressAsFlow().onFirst { state -> - binding.imageViewCover.newImageRequest(state.manga.coverUrl)?.run { + binding.imageViewCover.newImageRequest(state.manga.coverUrl, state.manga.source)?.run { referer(state.manga.publicUrl) placeholder(state.cover) fallback(R.drawable.ic_placeholder) @@ -60,6 +64,7 @@ fun downloadItemAD( binding.buttonCancel.isVisible = false binding.buttonResume.isVisible = false } + is DownloadState.Done -> { binding.textViewStatus.setText(R.string.download_complete) binding.progressBar.isIndeterminate = false @@ -69,6 +74,7 @@ fun downloadItemAD( binding.buttonCancel.isVisible = false binding.buttonResume.isVisible = false } + is DownloadState.Error -> { binding.textViewStatus.setText(R.string.error_occurred) binding.progressBar.isIndeterminate = false @@ -79,6 +85,7 @@ fun downloadItemAD( binding.buttonCancel.isVisible = state.canRetry binding.buttonResume.isVisible = state.canRetry } + is DownloadState.PostProcessing -> { binding.textViewStatus.setText(R.string.processing_) binding.progressBar.isIndeterminate = true @@ -88,6 +95,7 @@ fun downloadItemAD( binding.buttonCancel.isVisible = false binding.buttonResume.isVisible = false } + is DownloadState.Preparing -> { binding.textViewStatus.setText(R.string.preparing_) binding.progressBar.isIndeterminate = true @@ -97,6 +105,7 @@ fun downloadItemAD( binding.buttonCancel.isVisible = true binding.buttonResume.isVisible = false } + is DownloadState.Progress -> { binding.textViewStatus.setText(R.string.manga_downloading_) binding.progressBar.isIndeterminate = false @@ -109,6 +118,7 @@ fun downloadItemAD( binding.buttonCancel.isVisible = true binding.buttonResume.isVisible = false } + is DownloadState.Queued -> { binding.textViewStatus.setText(R.string.queued) binding.progressBar.isIndeterminate = false diff --git a/app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapterDelegates.kt b/app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapterDelegates.kt index c1cf4f753..0c9712fcd 100644 --- a/app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapterDelegates.kt +++ b/app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapterDelegates.kt @@ -76,7 +76,7 @@ fun exploreSourceListItemAD( bind { binding.textViewTitle.text = item.source.title val fallbackIcon = FaviconFallbackDrawable(context, item.source.name) - binding.imageViewIcon.newImageRequest(item.source.faviconUri())?.run { + binding.imageViewIcon.newImageRequest(item.source.faviconUri(), item.source)?.run { fallback(fallbackIcon) placeholder(fallbackIcon) error(fallbackIcon) diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryAD.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryAD.kt index db3ba22be..8c633bcfb 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryAD.kt @@ -5,7 +5,9 @@ import android.graphics.Color import android.graphics.drawable.ColorDrawable import android.view.MotionEvent import android.view.View -import android.view.View.* +import android.view.View.OnClickListener +import android.view.View.OnLongClickListener +import android.view.View.OnTouchListener import androidx.core.graphics.ColorUtils import androidx.core.view.isVisible import androidx.core.widget.ImageViewCompat @@ -16,7 +18,11 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.databinding.ItemCategoryBinding import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesListListener import org.koitharu.kotatsu.list.ui.model.ListModel -import org.koitharu.kotatsu.utils.ext.* +import org.koitharu.kotatsu.utils.ext.animatorDurationScale +import org.koitharu.kotatsu.utils.ext.disposeImageRequest +import org.koitharu.kotatsu.utils.ext.enqueueWith +import org.koitharu.kotatsu.utils.ext.getThemeColor +import org.koitharu.kotatsu.utils.ext.newImageRequest fun categoryAD( coil: ImageLoader, diff --git a/app/src/main/java/org/koitharu/kotatsu/image/ui/ImageActivity.kt b/app/src/main/java/org/koitharu/kotatsu/image/ui/ImageActivity.kt index c8e5300a2..0fe13a2d3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/image/ui/ImageActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/image/ui/ImageActivity.kt @@ -17,11 +17,12 @@ import coil.target.ViewTarget import com.davemorrissey.labs.subscaleview.ImageSource import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject import org.koitharu.kotatsu.base.ui.BaseActivity import org.koitharu.kotatsu.databinding.ActivityImageBinding +import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.utils.ext.enqueueWith import org.koitharu.kotatsu.utils.ext.indicator +import javax.inject.Inject @AndroidEntryPoint class ImageActivity : BaseActivity() { @@ -56,6 +57,7 @@ class ImageActivity : BaseActivity() { .data(url) .memoryCachePolicy(CachePolicy.DISABLED) .lifecycle(this) + .tag(intent.getSerializableExtra(EXTRA_SOURCE) as? MangaSource) .target(SsivTarget(binding.ssiv)) .indicator(binding.progressBar) .enqueueWith(coil) @@ -88,9 +90,12 @@ class ImageActivity : BaseActivity() { companion object { - fun newIntent(context: Context, url: String): Intent { + private const val EXTRA_SOURCE = "source" + + fun newIntent(context: Context, url: String, source: MangaSource?): Intent { return Intent(context, ImageActivity::class.java) .setData(Uri.parse(url)) + .putExtra(EXTRA_SOURCE, source) } } } diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt index 01c09394e..ba9ccf454 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt @@ -177,7 +177,7 @@ abstract class MangaListFragment : private fun onError(e: Throwable) { if (e is CloudFlareProtectedException) { - CloudFlareDialog.newInstance(e.url).show(childFragmentManager, CloudFlareDialog.TAG) + CloudFlareDialog.newInstance(e.url, e.headers).show(childFragmentManager, CloudFlareDialog.TAG) } else { Snackbar.make( binding.recyclerView, diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt index 7484c6166..6e65e6f83 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt @@ -39,7 +39,7 @@ fun mangaGridItemAD( bind { payloads -> binding.textViewTitle.text = item.title binding.progressView.setPercent(item.progress, MangaListAdapter.PAYLOAD_PROGRESS in payloads) - binding.imageViewCover.newImageRequest(item.coverUrl)?.run { + binding.imageViewCover.newImageRequest(item.coverUrl, item.source)?.run { referer(item.manga.publicUrl) size(CoverSizeResolver(binding.imageViewCover)) placeholder(R.drawable.ic_placeholder) diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt index 1caac32e5..6f7412361 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt @@ -52,7 +52,7 @@ fun mangaListDetailedItemAD( binding.textViewTitle.text = item.title binding.textViewSubtitle.textAndVisible = item.subtitle binding.progressView.setPercent(item.progress, MangaListAdapter.PAYLOAD_PROGRESS in payloads) - binding.imageViewCover.newImageRequest(item.coverUrl)?.run { + binding.imageViewCover.newImageRequest(item.coverUrl, item.source)?.run { referer(item.manga.publicUrl) size(CoverSizeResolver(binding.imageViewCover)) placeholder(R.drawable.ic_placeholder) diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt index 36aa1ada0..dea006ed6 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt @@ -10,7 +10,11 @@ import org.koitharu.kotatsu.databinding.ItemMangaListBinding import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.MangaListModel import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.utils.ext.* +import org.koitharu.kotatsu.utils.ext.disposeImageRequest +import org.koitharu.kotatsu.utils.ext.enqueueWith +import org.koitharu.kotatsu.utils.ext.newImageRequest +import org.koitharu.kotatsu.utils.ext.referer +import org.koitharu.kotatsu.utils.ext.textAndVisible fun mangaListItemAD( coil: ImageLoader, @@ -31,7 +35,7 @@ fun mangaListItemAD( bind { binding.textViewTitle.text = item.title binding.textViewSubtitle.textAndVisible = item.subtitle - binding.imageViewCover.newImageRequest(item.coverUrl)?.run { + binding.imageViewCover.newImageRequest(item.coverUrl, item.source)?.run { referer(item.manga.publicUrl) placeholder(R.drawable.ic_placeholder) fallback(R.drawable.ic_placeholder) diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaItemModel.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaItemModel.kt index ce5145d26..2d4710a70 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaItemModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaItemModel.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.list.ui.model import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaSource sealed interface MangaItemModel : ListModel { @@ -10,4 +11,7 @@ sealed interface MangaItemModel : ListModel { val coverUrl: String val counter: Int val progress: Float -} \ No newline at end of file + + val source: MangaSource + get() = manga.source +} diff --git a/app/src/main/java/org/koitharu/kotatsu/local/ui/ImportService.kt b/app/src/main/java/org/koitharu/kotatsu/local/ui/ImportService.kt index 1ae9dc6c7..ae7d5aa60 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/ui/ImportService.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/ui/ImportService.kt @@ -99,7 +99,11 @@ class ImportService : CoroutineIntentService() { if (manga != null) { notification.setLargeIcon( coil.execute( - ImageRequest.Builder(applicationContext).data(manga.coverUrl).referer(manga.publicUrl).build(), + ImageRequest.Builder(applicationContext) + .data(manga.coverUrl) + .tag(manga.source) + .referer(manga.publicUrl) + .build(), ).toBitmapOrNull(), ) notification.setSubText(manga.title) diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt b/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt index 0ac53f720..f90f8397b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt @@ -191,6 +191,7 @@ class PageLoader @Inject constructor( .header(CommonHeaders.REFERER, page.referer) .header(CommonHeaders.ACCEPT, "image/webp,image/png;q=0.9,image/jpeg,*/*;q=0.8") .cacheControl(CommonHeaders.CACHE_CONTROL_DISABLED) + .tag(page.source) .build() okHttp.newCall(request).await().use { response -> check(response.isSuccessful) { diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt index ee94a4f87..2696f393f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt @@ -13,11 +13,9 @@ import coil.ImageLoader import coil.request.ImageRequest import coil.size.Scale import coil.size.ViewSizeResolver -import com.google.android.material.R as materialR import com.google.android.material.slider.LabelFormatter import com.google.android.material.slider.Slider import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.ui.BaseActivity import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga @@ -27,7 +25,14 @@ import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.util.format import org.koitharu.kotatsu.reader.domain.ReaderColorFilter -import org.koitharu.kotatsu.utils.ext.* +import org.koitharu.kotatsu.utils.ext.assistedViewModels +import org.koitharu.kotatsu.utils.ext.decodeRegion +import org.koitharu.kotatsu.utils.ext.enqueueWith +import org.koitharu.kotatsu.utils.ext.getParcelableExtraCompat +import org.koitharu.kotatsu.utils.ext.referer +import org.koitharu.kotatsu.utils.ext.setValueRounded +import javax.inject.Inject +import com.google.android.material.R as materialR @AndroidEntryPoint class ColorFilterConfigActivity : @@ -115,6 +120,7 @@ class ColorFilterConfigActivity : .referer(preview.referer) .scale(Scale.FILL) .decodeRegion() + .tag(preview.source) .error(R.drawable.ic_error_placeholder) .size(ViewSizeResolver(binding.imageViewBefore)) .allowRgb565(false) diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt index d992f747a..fd881846f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt @@ -5,9 +5,12 @@ import coil.ImageLoader import coil.request.ImageRequest import coil.size.Scale import coil.size.Size -import com.google.android.material.R as materialR import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener import org.koitharu.kotatsu.databinding.ItemPageThumbBinding @@ -19,6 +22,7 @@ import org.koitharu.kotatsu.utils.ext.isLowRamDevice import org.koitharu.kotatsu.utils.ext.referer import org.koitharu.kotatsu.utils.ext.runCatchingCancellable import org.koitharu.kotatsu.utils.ext.setTextColorAttr +import com.google.android.material.R as materialR fun pageThumbnailAD( coil: ImageLoader, @@ -41,6 +45,7 @@ fun pageThumbnailAD( ImageRequest.Builder(context) .data(url) .referer(item.page.referer) + .tag(item.page.source) .size(thumbSize) .scale(Scale.FILL) .allowRgb565(true) diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionSourceAD.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionSourceAD.kt index 5367bcbc3..086d52f39 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionSourceAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionSourceAD.kt @@ -17,7 +17,7 @@ fun searchSuggestionSourceAD( lifecycleOwner: LifecycleOwner, listener: SearchSuggestionListener, ) = adapterDelegateViewBinding( - { inflater, parent -> ItemSearchSuggestionSourceBinding.inflate(inflater, parent, false) } + { inflater, parent -> ItemSearchSuggestionSourceBinding.inflate(inflater, parent, false) }, ) { binding.switchLocal.setOnCheckedChangeListener { _, isChecked -> @@ -31,7 +31,7 @@ fun searchSuggestionSourceAD( binding.textViewTitle.text = item.source.title binding.switchLocal.isChecked = item.isEnabled val fallbackIcon = FaviconFallbackDrawable(context, item.source.name) - binding.imageViewCover.newImageRequest(item.source.faviconUri())?.run { + binding.imageViewCover.newImageRequest(item.source.faviconUri(), item.source)?.run { fallback(fallbackIcon) placeholder(fallbackIcon) error(fallbackIcon) @@ -43,4 +43,4 @@ fun searchSuggestionSourceAD( onViewRecycled { binding.imageViewCover.disposeImageRequest() } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionsMangaListAD.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionsMangaListAD.kt index 7c108274a..b451a7997 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionsMangaListAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionsMangaListAD.kt @@ -55,7 +55,7 @@ private fun searchSuggestionMangaGridAD( } bind { - binding.imageViewCover.newImageRequest(item.coverUrl)?.run { + binding.imageViewCover.newImageRequest(item.coverUrl, item.source)?.run { placeholder(R.drawable.ic_placeholder) fallback(R.drawable.ic_placeholder) error(R.drawable.ic_error_placeholder) diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt b/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt index 299f35ad7..cd0471af2 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt @@ -20,7 +20,7 @@ import org.koitharu.kotatsu.utils.image.FaviconFallbackDrawable fun sourceConfigHeaderDelegate() = adapterDelegateViewBinding( - { layoutInflater, parent -> ItemFilterHeaderBinding.inflate(layoutInflater, parent, false) } + { layoutInflater, parent -> ItemFilterHeaderBinding.inflate(layoutInflater, parent, false) }, ) { bind { @@ -31,7 +31,7 @@ fun sourceConfigHeaderDelegate() = fun sourceConfigGroupDelegate( listener: SourceConfigListener, ) = adapterDelegateViewBinding( - { layoutInflater, parent -> ItemExpandableBinding.inflate(layoutInflater, parent, false) } + { layoutInflater, parent -> ItemExpandableBinding.inflate(layoutInflater, parent, false) }, ) { binding.root.setOnClickListener { @@ -50,7 +50,7 @@ fun sourceConfigItemDelegate( lifecycleOwner: LifecycleOwner, ) = adapterDelegateViewBinding( { layoutInflater, parent -> ItemSourceConfigBinding.inflate(layoutInflater, parent, false) }, - on = { item, _, _ -> item is SourceConfigItem.SourceItem && !item.isDraggable } + on = { item, _, _ -> item is SourceConfigItem.SourceItem && !item.isDraggable }, ) { binding.switchToggle.setOnCheckedChangeListener { _, isChecked -> @@ -62,7 +62,7 @@ fun sourceConfigItemDelegate( binding.switchToggle.isChecked = item.isEnabled binding.textViewDescription.textAndVisible = item.summary val fallbackIcon = FaviconFallbackDrawable(context, item.source.name) - binding.imageViewIcon.newImageRequest(item.source.faviconUri())?.run { + binding.imageViewIcon.newImageRequest(item.source.faviconUri(), item.source)?.run { crossfade(context) error(fallbackIcon) placeholder(fallbackIcon) @@ -82,7 +82,7 @@ fun sourceConfigDraggableItemDelegate( listener: SourceConfigListener, ) = adapterDelegateViewBinding( { layoutInflater, parent -> ItemSourceConfigDraggableBinding.inflate(layoutInflater, parent, false) }, - on = { item, _, _ -> item is SourceConfigItem.SourceItem && item.isDraggable } + on = { item, _, _ -> item is SourceConfigItem.SourceItem && item.isDraggable }, ) { val eventListener = object : @@ -117,5 +117,5 @@ fun sourceConfigDraggableItemDelegate( } fun sourceConfigEmptySearchDelegate() = adapterDelegate( - R.layout.item_sources_empty -) { } \ No newline at end of file + R.layout.item_sources_empty, +) { } diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt b/app/src/main/java/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt index 4cac8671f..f9ce14a07 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt @@ -11,9 +11,7 @@ import androidx.activity.result.contract.ActivityResultContract import androidx.core.graphics.Insets import androidx.core.view.isVisible import androidx.core.view.updatePadding -import com.google.android.material.R as materialR import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.ui.BaseActivity import org.koitharu.kotatsu.browser.BrowserCallback @@ -26,6 +24,8 @@ import org.koitharu.kotatsu.databinding.ActivityBrowserBinding import org.koitharu.kotatsu.parsers.MangaParserAuthProvider import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.utils.TaggedActivityResult +import javax.inject.Inject +import com.google.android.material.R as materialR @AndroidEntryPoint class SourceAuthActivity : BaseActivity(), BrowserCallback { @@ -44,7 +44,8 @@ class SourceAuthActivity : BaseActivity(), BrowserCallba finishAfterTransition() return } - authProvider = (mangaRepositoryFactory.create(source) as? RemoteMangaRepository)?.getAuthProvider() ?: run { + val repository = mangaRepositoryFactory.create(source) as? RemoteMangaRepository + authProvider = (repository)?.getAuthProvider() ?: run { Toast.makeText( this, getString(R.string.auth_not_supported_by, source.title), @@ -59,7 +60,7 @@ class SourceAuthActivity : BaseActivity(), BrowserCallba } with(binding.webView.settings) { javaScriptEnabled = true - userAgentString = UserAgentInterceptor.userAgentChrome + userAgentString = repository.userAgent ?: UserAgentInterceptor.userAgent } binding.webView.webViewClient = BrowserClient(this) binding.webView.webChromeClient = ProgressChromeClient(binding.progressBar) @@ -96,6 +97,7 @@ class SourceAuthActivity : BaseActivity(), BrowserCallba finishAfterTransition() true } + else -> super.onOptionsItemSelected(item) } diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedItemAD.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedItemAD.kt index b98b25e17..901e4573a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedItemAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedItemAD.kt @@ -28,7 +28,7 @@ fun feedItemAD( bind { binding.textViewTitle.isBold = item.isNew binding.textViewSummary.isBold = item.isNew - binding.imageViewCover.newImageRequest(item.imageUrl)?.run { + binding.imageViewCover.newImageRequest(item.imageUrl, item.manga.source)?.run { placeholder(R.drawable.ic_placeholder) fallback(R.drawable.ic_placeholder) error(R.drawable.ic_error_placeholder) diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/work/TrackWorker.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/work/TrackWorker.kt index fa488b146..4aa0b5a86 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/work/TrackWorker.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/work/TrackWorker.kt @@ -155,7 +155,11 @@ class TrackWorker @AssistedInject constructor( setNumber(newChapters.size) setLargeIcon( coil.execute( - ImageRequest.Builder(applicationContext).data(manga.coverUrl).referer(manga.publicUrl).build(), + ImageRequest.Builder(applicationContext) + .data(manga.coverUrl) + .referer(manga.publicUrl) + .tag(manga.source) + .build(), ).toBitmapOrNull(), ) setSmallIcon(R.drawable.ic_stat_book_plus) diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/CoilExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/CoilExt.kt index 914947ba2..28716c743 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/CoilExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/CoilExt.kt @@ -13,16 +13,18 @@ import com.google.android.material.progressindicator.BaseProgressIndicator import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.network.CommonHeaders +import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.utils.image.RegionBitmapDecoder import org.koitharu.kotatsu.utils.progress.ImageRequestIndicatorListener -fun ImageView.newImageRequest(url: Any?): ImageRequest.Builder? { +fun ImageView.newImageRequest(url: Any?, mangaSource: MangaSource? = null): ImageRequest.Builder? { val current = CoilUtils.result(this) if (current != null && current.request.data == url) { return null } return ImageRequest.Builder(context) .data(url) + .tag(mangaSource) .crossfade(context) .target(this) } @@ -45,6 +47,7 @@ fun ImageResult.toBitmapOrNull() = when (this) { } catch (_: Throwable) { null } + is ErrorResult -> null } diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt b/app/src/main/java/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt index 88487c636..c023f9d05 100644 --- a/app/src/main/java/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt +++ b/app/src/main/java/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt @@ -53,6 +53,7 @@ class RecentListFactory( ImageRequest.Builder(context) .data(item.coverUrl) .size(coverSize) + .tag(item.source) .transformations(transformation) .build(), ).requireBitmap() diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfListFactory.kt b/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfListFactory.kt index 6572418d3..f3dd62b87 100644 --- a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfListFactory.kt +++ b/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfListFactory.kt @@ -64,6 +64,7 @@ class ShelfListFactory( ImageRequest.Builder(context) .data(item.coverUrl) .size(coverSize) + .tag(item.source) .transformations(transformation) .build(), ).requireBitmap()