diff --git a/app/build.gradle b/app/build.gradle index dae9e6369..67f37754c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -19,7 +19,7 @@ android { applicationId 'org.koitharu.kotatsu' minSdk = 21 targetSdk = 35 - versionCode = 1006 + versionCode = 1007 versionName = '8.1.1' generatedDensities = [] testInstrumentationRunner 'org.koitharu.kotatsu.HiltTestRunner' diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/browser/BaseBrowserActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/BaseBrowserActivity.kt index 95f69e868..dd7d9421d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/browser/BaseBrowserActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/browser/BaseBrowserActivity.kt @@ -6,10 +6,18 @@ import androidx.core.view.WindowInsetsCompat import androidx.core.view.isVisible import androidx.core.view.updatePadding import dagger.hilt.android.AndroidEntryPoint +import org.koitharu.kotatsu.core.model.MangaSource +import org.koitharu.kotatsu.core.nav.AppRouter +import org.koitharu.kotatsu.core.network.CommonHeaders import org.koitharu.kotatsu.core.network.proxy.ProxyProvider +import org.koitharu.kotatsu.core.parser.MangaRepository +import org.koitharu.kotatsu.core.parser.ParserMangaRepository import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.util.ext.configureForParser import org.koitharu.kotatsu.core.util.ext.consumeAll import org.koitharu.kotatsu.databinding.ActivityBrowserBinding +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.util.nullIfEmpty import javax.inject.Inject @AndroidEntryPoint @@ -18,6 +26,9 @@ abstract class BaseBrowserActivity : BaseActivity(), Bro @Inject lateinit var proxyProvider: ProxyProvider + @Inject + lateinit var mangaRepositoryFactory: MangaRepository.Factory + private lateinit var onBackPressedCallback: WebViewBackPressedCallback override fun onCreate(savedInstanceState: Bundle?) { @@ -28,10 +39,21 @@ abstract class BaseBrowserActivity : BaseActivity(), Bro viewBinding.webView.webChromeClient = ProgressChromeClient(viewBinding.progressBar) onBackPressedCallback = WebViewBackPressedCallback(viewBinding.webView) onBackPressedDispatcher.addCallback(onBackPressedCallback) - onCreate2(savedInstanceState) + + val mangaSource = MangaSource(intent?.getStringExtra(AppRouter.KEY_SOURCE)) + val repository = mangaRepositoryFactory.create(mangaSource) as? ParserMangaRepository + val userAgent = intent?.getStringExtra(AppRouter.KEY_USER_AGENT)?.nullIfEmpty() + ?: repository?.getRequestHeaders()?.get(CommonHeaders.USER_AGENT) + viewBinding.webView.configureForParser(userAgent) + + onCreate2(savedInstanceState, mangaSource, repository) } - protected abstract fun onCreate2(savedInstanceState: Bundle?) + protected abstract fun onCreate2( + savedInstanceState: Bundle?, + source: MangaSource, + repository: ParserMangaRepository? + ) override fun onApplyWindowInsets( v: View, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/browser/BrowserActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/BrowserActivity.kt index aba7db14f..64044071f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/browser/BrowserActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/browser/BrowserActivity.kt @@ -8,30 +8,19 @@ import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.launch import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.model.MangaSource import org.koitharu.kotatsu.core.nav.AppRouter import org.koitharu.kotatsu.core.nav.router -import org.koitharu.kotatsu.core.network.CommonHeaders -import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.ParserMangaRepository -import org.koitharu.kotatsu.core.util.ext.configureForParser import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug -import javax.inject.Inject +import org.koitharu.kotatsu.parsers.model.MangaSource @AndroidEntryPoint class BrowserActivity : BaseBrowserActivity() { - @Inject - lateinit var mangaRepositoryFactory: MangaRepository.Factory - - override fun onCreate2(savedInstanceState: Bundle?) { - setDisplayHomeAsUp(true, true) - val mangaSource = MangaSource(intent?.getStringExtra(AppRouter.KEY_SOURCE)) - val repository = mangaRepositoryFactory.create(mangaSource) as? ParserMangaRepository - val userAgent = repository?.getRequestHeaders()?.get(CommonHeaders.USER_AGENT) - viewBinding.webView.configureForParser(userAgent) - viewBinding.webView.webViewClient = BrowserClient(proxyProvider, this) + override fun onCreate2(savedInstanceState: Bundle?, source: MangaSource, repository: ParserMangaRepository?) { + setDisplayHomeAsUp(isEnabled = true, showUpAsClose = true) + viewBinding.webView.webViewClient = BrowserClient(this) lifecycleScope.launch { try { proxyProvider.applyWebViewConfig() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/browser/BrowserClient.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/BrowserClient.kt index 9d72bcfe7..053f1074f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/browser/BrowserClient.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/browser/BrowserClient.kt @@ -3,10 +3,8 @@ package org.koitharu.kotatsu.browser import android.graphics.Bitmap import android.webkit.WebView import androidx.webkit.WebViewClientCompat -import org.koitharu.kotatsu.core.network.proxy.ProxyProvider open class BrowserClient( - private val proxyProvider: ProxyProvider, private val callback: BrowserCallback ) : WebViewClientCompat() { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareActivity.kt index b5946c6b0..cb17ca1cc 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareActivity.kt @@ -22,9 +22,11 @@ import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException import org.koitharu.kotatsu.core.model.MangaSource import org.koitharu.kotatsu.core.nav.AppRouter import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar -import org.koitharu.kotatsu.core.util.ext.configureForParser +import org.koitharu.kotatsu.core.parser.ParserMangaRepository import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.network.CloudFlareHelper +import org.koitharu.kotatsu.parsers.util.ifNullOrEmpty import javax.inject.Inject @AndroidEntryPoint @@ -37,15 +39,14 @@ class CloudFlareActivity : BaseBrowserActivity(), CloudFlareCallback { private lateinit var cfClient: CloudFlareClient - override fun onCreate2(savedInstanceState: Bundle?) { - setDisplayHomeAsUp(true, true) + override fun onCreate2(savedInstanceState: Bundle?, source: MangaSource, repository: ParserMangaRepository?) { + setDisplayHomeAsUp(isEnabled = true, showUpAsClose = true) val url = intent?.dataString if (url.isNullOrEmpty()) { finishAfterTransition() return } - cfClient = CloudFlareClient(proxyProvider, cookieJar, this, url) - viewBinding.webView.configureForParser(intent?.getStringExtra(AppRouter.KEY_USER_AGENT)) + cfClient = CloudFlareClient(cookieJar, this, url) viewBinding.webView.webViewClient = cfClient lifecycleScope.launch { try { @@ -106,8 +107,7 @@ class CloudFlareActivity : BaseBrowserActivity(), CloudFlareCallback { override fun onTitleChanged(title: CharSequence, subtitle: CharSequence?) { setTitle(title) - supportActionBar?.subtitle = - subtitle?.toString()?.toHttpUrlOrNull()?.topPrivateDomain() ?: subtitle + supportActionBar?.subtitle = subtitle?.toString()?.toHttpUrlOrNull()?.host.ifNullOrEmpty { subtitle } } private fun restartCheck() { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareClient.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareClient.kt index 18c353c03..5cb637a16 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareClient.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareClient.kt @@ -4,17 +4,15 @@ import android.graphics.Bitmap import android.webkit.WebView import org.koitharu.kotatsu.browser.BrowserClient import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar -import org.koitharu.kotatsu.core.network.proxy.ProxyProvider import org.koitharu.kotatsu.parsers.network.CloudFlareHelper private const val LOOP_COUNTER = 3 class CloudFlareClient( - proxyProvider: ProxyProvider, private val cookieJar: MutableCookieJar, private val callback: CloudFlareCallback, private val targetUrl: String, -) : BrowserClient(proxyProvider, callback) { +) : BrowserClient(callback) { private val oldClearance = getClearance() private var counter = 0 diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsActivity.kt index 93b8c6b53..f4cf5a0b8 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsActivity.kt @@ -34,7 +34,6 @@ import org.koitharu.kotatsu.settings.search.SettingsItem import org.koitharu.kotatsu.settings.search.SettingsSearchFragment import org.koitharu.kotatsu.settings.search.SettingsSearchViewModel import org.koitharu.kotatsu.settings.sources.SourceSettingsFragment -import org.koitharu.kotatsu.settings.sources.SourceSettingsFragment.Companion.EXTRA_SOURCE import org.koitharu.kotatsu.settings.sources.SourcesSettingsFragment import org.koitharu.kotatsu.settings.sources.manage.SourcesManageFragment import org.koitharu.kotatsu.settings.tracker.TrackerSettingsFragment @@ -57,7 +56,7 @@ class SettingsActivity : override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(ActivitySettingsBinding.inflate(layoutInflater)) - setDisplayHomeAsUp(true, false) + setDisplayHomeAsUp(isEnabled = true, showUpAsClose = false) val fm = supportFragmentManager val currentFragment = fm.findFragmentById(R.id.container) if (currentFragment == null || (isMasterDetails && currentFragment is RootSettingsFragment)) { @@ -151,7 +150,7 @@ class SettingsActivity : AppRouter.ACTION_PROXY -> ProxySettingsFragment() AppRouter.ACTION_MANAGE_DOWNLOADS -> DownloadsSettingsFragment() AppRouter.ACTION_SOURCE -> SourceSettingsFragment.newInstance( - MangaSource(intent.getStringExtra(EXTRA_SOURCE)), + MangaSource(intent.getStringExtra(AppRouter.KEY_SOURCE)), ) AppRouter.ACTION_MANAGE_SOURCES -> SourcesManageFragment() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourceSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourceSettingsFragment.kt index f183b971e..68d5675d7 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourceSettingsFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourceSettingsFragment.kt @@ -9,6 +9,7 @@ import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver import org.koitharu.kotatsu.core.model.getTitle +import org.koitharu.kotatsu.core.nav.AppRouter import org.koitharu.kotatsu.core.nav.router import org.koitharu.kotatsu.core.parser.EmptyMangaRepository import org.koitharu.kotatsu.core.parser.ParserMangaRepository @@ -121,10 +122,8 @@ class SourceSettingsFragment : BasePreferenceFragment(0), Preference.OnPreferenc private const val KEY_AUTH = "auth" private const val KEY_ENABLE = "enable" - const val EXTRA_SOURCE = "source" - fun newInstance(source: MangaSource) = SourceSettingsFragment().withArgs(1) { - putString(EXTRA_SOURCE, source.name) + putString(AppRouter.KEY_SOURCE, source.name) } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourceSettingsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourceSettingsViewModel.kt index 6d23b430d..595e81dee 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourceSettingsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourceSettingsViewModel.kt @@ -9,6 +9,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import okhttp3.HttpUrl import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.model.MangaSource +import org.koitharu.kotatsu.core.nav.AppRouter import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar import org.koitharu.kotatsu.core.parser.CachingMangaRepository import org.koitharu.kotatsu.core.parser.MangaRepository @@ -32,7 +33,7 @@ class SourceSettingsViewModel @Inject constructor( private val mangaSourcesRepository: MangaSourcesRepository, ) : BaseViewModel(), SharedPreferences.OnSharedPreferenceChangeListener { - val source = MangaSource(savedStateHandle.get(SourceSettingsFragment.EXTRA_SOURCE)) + val source = MangaSource(savedStateHandle.get(AppRouter.KEY_SOURCE)) val repository = mangaRepositoryFactory.create(source) val onActionDone = MutableEventFlow() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt index a598b7548..a119b0caa 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt @@ -14,46 +14,34 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.browser.BaseBrowserActivity import org.koitharu.kotatsu.browser.BrowserCallback import org.koitharu.kotatsu.browser.BrowserClient -import org.koitharu.kotatsu.core.model.MangaSource +import org.koitharu.kotatsu.core.model.getTitle import org.koitharu.kotatsu.core.nav.AppRouter -import org.koitharu.kotatsu.core.network.CommonHeaders -import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.ParserMangaRepository -import org.koitharu.kotatsu.core.util.ext.configureForParser import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.parsers.MangaParserAuthProvider -import org.koitharu.kotatsu.parsers.model.MangaParserSource import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.settings.sources.SourceSettingsFragment.Companion.EXTRA_SOURCE -import javax.inject.Inject @AndroidEntryPoint class SourceAuthActivity : BaseBrowserActivity(), BrowserCallback { - @Inject - lateinit var mangaRepositoryFactory: MangaRepository.Factory - private lateinit var authProvider: MangaParserAuthProvider - override fun onCreate2(savedInstanceState: Bundle?) { - val source = MangaSource(intent?.getStringExtra(EXTRA_SOURCE)) - if (source !is MangaParserSource) { + override fun onCreate2(savedInstanceState: Bundle?, source: MangaSource, repository: ParserMangaRepository?) { + if (repository == null) { finishAfterTransition() return } - val repository = mangaRepositoryFactory.create(source) as? ParserMangaRepository - authProvider = (repository)?.getAuthProvider() ?: run { + authProvider = repository.getAuthProvider() ?: run { Toast.makeText( this, - getString(R.string.auth_not_supported_by, source.title), + getString(R.string.auth_not_supported_by, source.getTitle(this)), Toast.LENGTH_SHORT, ).show() finishAfterTransition() return } - setDisplayHomeAsUp(true, true) - viewBinding.webView.configureForParser(repository.getRequestHeaders()[CommonHeaders.USER_AGENT]) - viewBinding.webView.webViewClient = BrowserClient(proxyProvider, this) + setDisplayHomeAsUp(isEnabled = true, showUpAsClose = true) + viewBinding.webView.webViewClient = BrowserClient(this) lifecycleScope.launch { try { proxyProvider.applyWebViewConfig() @@ -63,7 +51,7 @@ class SourceAuthActivity : BaseBrowserActivity(), BrowserCallback { if (savedInstanceState == null) { val url = authProvider.authUrl onTitleChanged( - source.title, + source.getTitle(this@SourceAuthActivity), getString(R.string.loading_), ) viewBinding.webView.loadUrl(url) @@ -92,13 +80,10 @@ class SourceAuthActivity : BaseBrowserActivity(), BrowserCallback { } class Contract : ActivityResultContract() { - override fun createIntent(context: Context, input: MangaSource): Intent { - return AppRouter.sourceAuthIntent(context, input) - } - override fun parseResult(resultCode: Int, intent: Intent?): Boolean { - return resultCode == RESULT_OK - } + override fun createIntent(context: Context, input: MangaSource) = AppRouter.sourceAuthIntent(context, input) + + override fun parseResult(resultCode: Int, intent: Intent?) = resultCode == RESULT_OK } companion object { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/manage/SourcesManageFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/manage/SourcesManageFragment.kt index 54cb47dd7..8bc1f6eae 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/manage/SourcesManageFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/manage/SourcesManageFragment.kt @@ -17,6 +17,7 @@ import coil3.ImageLoader import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.launch import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.nav.AppRouter import org.koitharu.kotatsu.core.nav.router import org.koitharu.kotatsu.core.os.AppShortcutManager import org.koitharu.kotatsu.core.prefs.AppSettings @@ -117,7 +118,7 @@ class SourcesManageFragment : override fun onItemSettingsClick(item: SourceConfigItem.SourceItem) { (activity as? SettingsActivity)?.openFragment( fragmentClass = SourceSettingsFragment::class.java, - args = Bundle(1).apply { putString(SourceSettingsFragment.EXTRA_SOURCE, item.source.name) }, + args = Bundle(1).apply { putString(AppRouter.KEY_SOURCE, item.source.name) }, isFromRoot = false, ) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index caee98fae..eea244385 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -31,7 +31,7 @@ material = "1.13.0-alpha12" moshi = "1.15.2" okhttp = "4.12.0" okio = "3.10.2" -parsers = "2ec2484982" +parsers = "b8376594" preference = "1.2.1" recyclerview = "1.4.0" room = "2.6.1"