Make default user agent string configurable

using custom preference class to add a reset button to the dialog

Co-Authored-By: arkon <4098258+arkon@users.noreply.github.com>
This commit is contained in:
Jays2Kings 2022-08-17 20:29:54 -04:00
parent 6bdc1948fc
commit 0de018c98f
9 changed files with 91 additions and 18 deletions

View file

@ -14,6 +14,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.updater.AutoAppUpdaterJob
import eu.kanade.tachiyomi.extension.model.InstalledExtensionsOrder
import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.ui.library.LibraryItem
import eu.kanade.tachiyomi.ui.library.filter.FilterBottomSheet
import eu.kanade.tachiyomi.ui.reader.settings.OrientationType
@ -435,6 +436,8 @@ class PreferencesHelper(val context: Context) {
fun dohProvider() = prefs.getInt(Keys.dohProvider, -1)
fun defaultUserAgent() = flowPrefs.getString("default_user_agent", NetworkHelper.DEFAULT_USER_AGENT)
fun showSeriesInShortcuts() = prefs.getBoolean(Keys.showSeriesInShortcuts, true)
fun showSourcesInShortcuts() = prefs.getBoolean(Keys.showSourcesInShortcuts, true)
fun openChapterInShortcuts() = prefs.getBoolean(Keys.openChapterInShortcuts, true)

View file

@ -61,4 +61,12 @@ class NetworkHelper(val context: Context) {
.addInterceptor(CloudflareInterceptor(context))
.build()
}
val defaultUserAgent by lazy {
preferences.defaultUserAgent().get()
}
companion object {
const val DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"
}
}

View file

@ -9,7 +9,6 @@ import android.widget.Toast
import androidx.core.content.ContextCompat
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.system.WebViewClientCompat
import eu.kanade.tachiyomi.util.system.WebViewUtil
import eu.kanade.tachiyomi.util.system.isOutdated
@ -109,7 +108,7 @@ class CloudflareInterceptor(private val context: Context) : Interceptor {
// Avoid sending empty User-Agent, Chromium WebView will reset to default if empty
webview.settings.userAgentString = request.header("User-Agent")
?: HttpSource.DEFAULT_USER_AGENT
?: networkHelper.defaultUserAgent
webview.webViewClient = object : WebViewClientCompat() {
override fun onPageFinished(view: WebView, url: String) {

View file

@ -1,10 +1,13 @@
package eu.kanade.tachiyomi.network.interceptor
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.network.NetworkHelper
import okhttp3.Interceptor
import okhttp3.Response
import uy.kohesive.injekt.injectLazy
class UserAgentInterceptor : Interceptor {
private val networkHelper: NetworkHelper by injectLazy()
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()
@ -12,7 +15,7 @@ class UserAgentInterceptor : Interceptor {
val newRequest = originalRequest
.newBuilder()
.removeHeader("User-Agent")
.addHeader("User-Agent", HttpSource.DEFAULT_USER_AGENT)
.addHeader("User-Agent", networkHelper.defaultUserAgent)
.build()
chain.proceed(newRequest)
} else {

View file

@ -35,13 +35,6 @@ abstract class HttpSource : CatalogueSource {
*/
protected val network: NetworkHelper by injectLazy()
// /**
// * Preferences that a source may need.
// */
// val preferences: SharedPreferences by lazy {
// Injekt.get<Application>().getSharedPreferences(source.getPreferenceKey(), Context.MODE_PRIVATE)
// }
/**
* Base url of the website without the trailing slash, like: http://mysite.com
*/
@ -79,7 +72,7 @@ abstract class HttpSource : CatalogueSource {
* Headers builder for requests. Implementations can override this method for custom headers.
*/
protected open fun headersBuilder() = Headers.Builder().apply {
add("User-Agent", DEFAULT_USER_AGENT)
add("User-Agent", network.defaultUserAgent)
}
/**
@ -378,8 +371,4 @@ abstract class HttpSource : CatalogueSource {
* Returns the list of filters for the source.
*/
override fun getFilterList() = FilterList()
companion object {
const val DEFAULT_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.124 Safari/537.36 Edg/102.0.1245.44"
}
}

View file

@ -23,6 +23,7 @@ import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.startAuthentication
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.widget.preference.AdaptiveTitlePreferenceCategory
import eu.kanade.tachiyomi.widget.preference.EditTextResetPreference
import eu.kanade.tachiyomi.widget.preference.IntListMatPreference
import eu.kanade.tachiyomi.widget.preference.ListMatPreference
import eu.kanade.tachiyomi.widget.preference.MultiListMatPreference
@ -53,8 +54,8 @@ inline fun PreferenceGroup.checkBoxPreference(block: (@DSL CheckBoxPreference).(
return initThenAdd(CheckBoxPreference(context), block)
}
inline fun PreferenceGroup.editTextPreference(block: (@DSL EditTextPreference).() -> Unit): EditTextPreference {
return initThenAdd(EditTextPreference(context), block).also(::initDialog)
inline fun PreferenceGroup.editTextPreference(activity: Activity?, block: (@DSL EditTextResetPreference).() -> Unit): EditTextResetPreference {
return initThenAdd(EditTextResetPreference(activity, context), block) // .also(::initDialog)
}
inline fun PreferenceGroup.dropDownPreference(block: (@DSL DropDownPreference).() -> Unit):
@ -168,6 +169,11 @@ fun <T> ListPreference.bindTo(preference: FlowPreference<T>) {
defaultValue = preference.defaultValue.toString()
}
fun <T> EditTextPreference.bindTo(preference: FlowPreference<T>) {
key = preference.key
defaultValue = preference.defaultValue.toString()
}
fun <T> ListMatPreference.bindTo(preference: FlowPreference<T>) {
key = preference.key
val defValue = preference.defaultValue

View file

@ -255,6 +255,15 @@ class SettingsAdvancedController : SettingsController() {
true
}
}
editTextPreference(activity) {
bindTo(preferences.defaultUserAgent())
titleRes = R.string.user_agent_string
onChange {
activity?.toast(R.string.requires_app_restart)
true
}
}
}
preferenceCategory {

View file

@ -0,0 +1,55 @@
package eu.kanade.tachiyomi.widget.preference
import android.app.Activity
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.EditText
import android.widget.TextView
import androidx.core.content.edit
import androidx.core.view.isVisible
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import eu.kanade.tachiyomi.R
class EditTextResetPreference @JvmOverloads constructor(
activity: Activity?,
context: Context,
attrs: AttributeSet? = null,
) :
MatPreference(activity, context, attrs) {
private var defValue: String = ""
override fun onSetInitialValue(defaultValue: Any?) {
super.onSetInitialValue(defaultValue)
defValue = defaultValue as? String ?: defValue
}
override var customSummaryProvider: SummaryProvider<MatPreference>? = SummaryProvider<MatPreference> {
sharedPreferences?.getString(key, defValue)
}
override fun dialog(): MaterialAlertDialogBuilder {
return super.dialog().apply {
val attrs = intArrayOf(android.R.attr.dialogLayout)
val a = context.obtainStyledAttributes(R.style.Preference_DialogPreference_EditTextPreference_Material, attrs)
val resourceId = a.getResourceId(0, 0)
val view = LayoutInflater.from(context).inflate(resourceId, null)
val textView = view.findViewById<EditText>(android.R.id.edit)
val message = view.findViewById<TextView>(android.R.id.message)
message?.isVisible = false
textView?.append(sharedPreferences?.getString(key, defValue))
this.setView(view)
this.setNeutralButton(R.string.reset) { _, _ ->
sharedPreferences?.edit { remove(key) }
callChangeListener(defValue)
notifyChanged()
}
this.setPositiveButton(android.R.string.ok) { _, _ ->
sharedPreferences?.edit { putString(key, textView.text.toString()) }
callChangeListener(textView.text.toString())
notifyChanged()
}
a.recycle()
}
}
}

View file

@ -807,6 +807,7 @@
<string name="crash_log_saved">Crash logs saved</string>
<string name="network">Network</string>
<string name="doh">DNS over HTTPS</string>
<string name="user_agent_string">Default user agent string</string>
<string name="disabled">Disabled</string>
<string name="cloudflare" translatable="false">Cloudflare</string>
<string name="google" translatable="false">Google</string>