diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt index 23df27186..7ca1c78f3 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt @@ -704,6 +704,7 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { const val KEY_LOGS_SHARE = "logs_share" const val KEY_APP_UPDATE = "app_update" const val KEY_APP_TRANSLATION = "about_app_translation" + const val PROXY_TEST = "proxy_test" // old keys are for migration only private const val KEY_IMAGES_PROXY_OLD = "images_proxy" diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/ProxySettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/ProxySettingsFragment.kt index 4125d46e2..188b9f28c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/ProxySettingsFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/ProxySettingsFragment.kt @@ -7,20 +7,40 @@ import android.view.inputmethod.EditorInfo import androidx.preference.EditTextPreference import androidx.preference.Preference import androidx.preference.PreferenceCategory +import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.OkHttpClient +import okhttp3.Request import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.network.BaseHttpClient import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.BasePreferenceFragment +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug +import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope +import org.koitharu.kotatsu.parsers.util.await import org.koitharu.kotatsu.settings.utils.EditTextBindListener import org.koitharu.kotatsu.settings.utils.PasswordSummaryProvider import org.koitharu.kotatsu.settings.utils.validation.DomainValidator import org.koitharu.kotatsu.settings.utils.validation.PortNumberValidator import java.net.Proxy +import javax.inject.Inject +import kotlin.coroutines.cancellation.CancellationException @AndroidEntryPoint class ProxySettingsFragment : BasePreferenceFragment(R.string.proxy), SharedPreferences.OnSharedPreferenceChangeListener { + private var testJob: Job? = null + + @Inject + @BaseHttpClient + lateinit var okHttpClient: OkHttpClient + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { addPreferencesFromResource(R.xml.pref_proxy) findPreference(AppSettings.KEY_PROXY_ADDRESS)?.setOnBindEditTextListener( @@ -60,6 +80,15 @@ class ProxySettingsFragment : BasePreferenceFragment(R.string.proxy), super.onDestroyView() } + override fun onPreferenceTreeClick(preference: Preference): Boolean = when (preference.key) { + AppSettings.PROXY_TEST -> { + testConnection() + true + } + + else -> super.onPreferenceTreeClick(preference) + } + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { when (key) { AppSettings.KEY_PROXY_TYPE -> updateDependencies() @@ -73,5 +102,47 @@ class ProxySettingsFragment : BasePreferenceFragment(R.string.proxy), findPreference(AppSettings.KEY_PROXY_AUTH)?.isEnabled = isProxyEnabled findPreference(AppSettings.KEY_PROXY_LOGIN)?.isEnabled = isProxyEnabled findPreference(AppSettings.KEY_PROXY_PASSWORD)?.isEnabled = isProxyEnabled + findPreference(AppSettings.PROXY_TEST)?.isEnabled = isProxyEnabled && testJob?.isActive != true + } + + private fun testConnection() { + testJob?.cancel() + testJob = viewLifecycleScope.launch { + val pref = findPreference(AppSettings.PROXY_TEST) + pref?.run { + setSummary(R.string.loading_) + isEnabled = false + } + try { + withContext(Dispatchers.Default) { + val request = Request.Builder() + .get() + .url("http://neverssl.com") + .build() + val response = okHttpClient.newCall(request).await() + check(response.isSuccessful) { response.message } + } + showTestResult(null) + } catch (e: CancellationException) { + throw e + } catch (e: Throwable) { + e.printStackTraceDebug() + showTestResult(e) + } finally { + pref?.run { + isEnabled = true + summary = null + } + } + } + } + + private fun showTestResult(error: Throwable?) { + MaterialAlertDialogBuilder(requireContext()) + .setTitle(R.string.proxy) + .setMessage(error?.getDisplayMessage(resources) ?: getString(R.string.connection_ok)) + .setPositiveButton(android.R.string.ok, null) + .setCancelable(true) + .show() } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a3ed043af..352f0cf20 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -670,4 +670,5 @@ Chapters left External/plugin Incompatible plugin or internal error. Make sure you are using the latest version of the plugin and Kotatsu + Connection is OK diff --git a/app/src/main/res/xml/pref_proxy.xml b/app/src/main/res/xml/pref_proxy.xml index 4b0447277..75f530990 100644 --- a/app/src/main/res/xml/pref_proxy.xml +++ b/app/src/main/res/xml/pref_proxy.xml @@ -36,4 +36,10 @@ + +