mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-05-29 05:10:20 +02:00
feat(YouTube/Alternative thumbnails): matches official ReVanced code
This commit is contained in:
parent
819348054b
commit
752c1df838
@ -3,18 +3,30 @@ package app.revanced.patches.youtube.alternativethumbnails.general
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.youtube.alternativethumbnails.general.fingerprints.CronetURLRequestCallbackOnResponseStartedFingerprint
|
||||
import app.revanced.patches.youtube.alternativethumbnails.general.fingerprints.CronetURLRequestCallbackOnSucceededFingerprint
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patches.youtube.alternativethumbnails.general.fingerprints.MessageDigestImageUrlFingerprint
|
||||
import app.revanced.patches.youtube.alternativethumbnails.general.fingerprints.MessageDigestImageUrlParentFingerprint
|
||||
import app.revanced.patches.youtube.alternativethumbnails.general.fingerprints.cronet.RequestFingerprint
|
||||
import app.revanced.patches.youtube.alternativethumbnails.general.fingerprints.cronet.request.callback.OnFailureFingerprint
|
||||
import app.revanced.patches.youtube.alternativethumbnails.general.fingerprints.cronet.request.callback.OnResponseStartedFingerprint
|
||||
import app.revanced.patches.youtube.alternativethumbnails.general.fingerprints.cronet.request.callback.OnSucceededFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.ALTERNATIVE_THUMBNAILS
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch.contexts
|
||||
import app.revanced.util.copyXmlNode
|
||||
import app.revanced.util.exception
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
|
||||
@Patch(
|
||||
name = "Alternative thumbnails",
|
||||
@ -50,53 +62,123 @@ import app.revanced.util.exception
|
||||
@Suppress("unused")
|
||||
object AlternativeThumbnailsPatch : BytecodePatch(
|
||||
setOf(
|
||||
CronetURLRequestCallbackOnResponseStartedFingerprint,
|
||||
MessageDigestImageUrlParentFingerprint
|
||||
MessageDigestImageUrlParentFingerprint,
|
||||
OnResponseStartedFingerprint,
|
||||
RequestFingerprint,
|
||||
)
|
||||
) {
|
||||
private lateinit var loadImageUrlMethod: MutableMethod
|
||||
private var loadImageUrlIndex = 0
|
||||
|
||||
private lateinit var loadImageSuccessCallbackMethod: MutableMethod
|
||||
private var loadImageSuccessCallbackIndex = 0
|
||||
|
||||
private lateinit var loadImageErrorCallbackMethod: MutableMethod
|
||||
private var loadImageErrorCallbackIndex = 0
|
||||
|
||||
/**
|
||||
* @param highPriority If the hook should be called before all other hooks.
|
||||
*/
|
||||
@Suppress("SameParameterValue")
|
||||
private fun addImageUrlHook(targetMethodClass: String, highPriority: Boolean) {
|
||||
loadImageUrlMethod.addInstructions(
|
||||
if (highPriority) 0 else loadImageUrlIndex,
|
||||
"""
|
||||
invoke-static { p1 }, $targetMethodClass->overrideImageURL(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object p1
|
||||
"""
|
||||
)
|
||||
loadImageUrlIndex += 2
|
||||
}
|
||||
|
||||
/**
|
||||
* If a connection completed, which includes normal 200 responses but also includes
|
||||
* status 404 and other error like http responses.
|
||||
*/
|
||||
@Suppress("SameParameterValue")
|
||||
private fun addImageUrlSuccessCallbackHook(targetMethodClass: String) {
|
||||
loadImageSuccessCallbackMethod.addInstruction(
|
||||
loadImageSuccessCallbackIndex++,
|
||||
"invoke-static { p1, p2 }, $targetMethodClass->handleCronetSuccess(" +
|
||||
"Lorg/chromium/net/UrlRequest;Lorg/chromium/net/UrlResponseInfo;)V"
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* If a connection outright failed to complete any connection.
|
||||
*/
|
||||
@Suppress("SameParameterValue")
|
||||
private fun addImageUrlErrorCallbackHook(targetMethodClass: String) {
|
||||
loadImageErrorCallbackMethod.addInstruction(
|
||||
loadImageErrorCallbackIndex++,
|
||||
"invoke-static { p1, p2, p3 }, $targetMethodClass->handleCronetFailure(" +
|
||||
"Lorg/chromium/net/UrlRequest;Lorg/chromium/net/UrlResponseInfo;Ljava/io/IOException;)V"
|
||||
)
|
||||
}
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
/**
|
||||
* Hook should should come first.
|
||||
*/
|
||||
MessageDigestImageUrlParentFingerprint.result?.let { parentResult ->
|
||||
MessageDigestImageUrlFingerprint.also {
|
||||
it.resolve(
|
||||
context,
|
||||
parentResult.classDef
|
||||
)
|
||||
}.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
fun MethodFingerprint.getResultOrThrow() =
|
||||
result ?: throw exception
|
||||
|
||||
fun MethodFingerprint.alsoResolve(fingerprint: MethodFingerprint) =
|
||||
also { resolve(context, fingerprint.getResultOrThrow().classDef) }.getResultOrThrow()
|
||||
|
||||
fun MethodFingerprint.resolveAndLetMutableMethod(
|
||||
fingerprint: MethodFingerprint,
|
||||
block: (MutableMethod) -> Unit
|
||||
) = alsoResolve(fingerprint).also { block(it.mutableMethod) }
|
||||
|
||||
MessageDigestImageUrlFingerprint.resolveAndLetMutableMethod(MessageDigestImageUrlParentFingerprint) {
|
||||
loadImageUrlMethod = it
|
||||
addImageUrlHook(ALTERNATIVE_THUMBNAILS, true)
|
||||
}
|
||||
|
||||
OnSucceededFingerprint.resolveAndLetMutableMethod(OnResponseStartedFingerprint) {
|
||||
loadImageSuccessCallbackMethod = it
|
||||
addImageUrlSuccessCallbackHook(ALTERNATIVE_THUMBNAILS)
|
||||
}
|
||||
|
||||
OnFailureFingerprint.resolveAndLetMutableMethod(OnResponseStartedFingerprint) {
|
||||
loadImageErrorCallbackMethod = it
|
||||
addImageUrlErrorCallbackHook(ALTERNATIVE_THUMBNAILS)
|
||||
}
|
||||
|
||||
// The URL is required for the failure callback hook, but the URL field is obfuscated.
|
||||
// Add a helper get method that returns the URL field.
|
||||
RequestFingerprint.getResultOrThrow().apply {
|
||||
// The url is the only string field that is set inside the constructor.
|
||||
val urlFieldInstruction = mutableMethod.getInstructions().first {
|
||||
if (it.opcode != Opcode.IPUT_OBJECT)
|
||||
return@first false
|
||||
|
||||
val reference = (it as ReferenceInstruction).reference as FieldReference
|
||||
reference.type == "Ljava/lang/String;"
|
||||
} as ReferenceInstruction
|
||||
|
||||
val urlFieldName = (urlFieldInstruction.reference as FieldReference).name
|
||||
val definingClass = RequestFingerprint.IMPLEMENTATION_CLASS_NAME
|
||||
val addedMethodName = "getHookedUrl"
|
||||
mutableClass.methods.add(
|
||||
ImmutableMethod(
|
||||
definingClass,
|
||||
addedMethodName,
|
||||
emptyList(),
|
||||
"Ljava/lang/String;",
|
||||
AccessFlags.PUBLIC.value,
|
||||
null,
|
||||
null,
|
||||
MutableMethodImplementation(2)
|
||||
).toMutable().apply {
|
||||
addInstructions(
|
||||
0, """
|
||||
invoke-static { p1 }, $ALTERNATIVE_THUMBNAILS->overrideImageURL(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object p1
|
||||
"""
|
||||
iget-object v0, p0, $definingClass->${urlFieldName}:Ljava/lang/String;
|
||||
return-object v0
|
||||
"""
|
||||
)
|
||||
}
|
||||
} ?: throw MessageDigestImageUrlFingerprint.exception
|
||||
} ?: throw MessageDigestImageUrlParentFingerprint.exception
|
||||
|
||||
|
||||
/**
|
||||
* If a connection completed, which includes normal 200 responses but also includes
|
||||
* status 404 and other error like http responses.
|
||||
*/
|
||||
CronetURLRequestCallbackOnResponseStartedFingerprint.result?.let { parentResult ->
|
||||
CronetURLRequestCallbackOnSucceededFingerprint.also {
|
||||
it.resolve(
|
||||
context,
|
||||
parentResult.classDef
|
||||
)
|
||||
}.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
addInstruction(
|
||||
0,
|
||||
"invoke-static { p2 }, $ALTERNATIVE_THUMBNAILS->handleCronetSuccess(Lorg/chromium/net/UrlResponseInfo;)V"
|
||||
)
|
||||
}
|
||||
} ?: throw CronetURLRequestCallbackOnSucceededFingerprint.exception
|
||||
} ?: throw CronetURLRequestCallbackOnResponseStartedFingerprint.exception
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy arrays
|
||||
|
@ -4,7 +4,7 @@ import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
object MessageDigestImageUrlFingerprint : MethodFingerprint(
|
||||
internal object MessageDigestImageUrlFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
parameters = listOf("Ljava/lang/String;", "L")
|
||||
parameters = listOf("Ljava/lang/String;", "L")
|
||||
)
|
@ -4,9 +4,9 @@ import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
object MessageDigestImageUrlParentFingerprint : MethodFingerprint(
|
||||
internal object MessageDigestImageUrlParentFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
returnType = "Ljava/lang/String;",
|
||||
returnType = "Ljava/lang/String;",
|
||||
parameters = emptyList(),
|
||||
strings = listOf("@#&=*+-_.,:!?()/~'%;\$"),
|
||||
)
|
@ -0,0 +1,16 @@
|
||||
package app.revanced.patches.youtube.alternativethumbnails.general.fingerprints.cronet
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.alternativethumbnails.general.fingerprints.cronet.RequestFingerprint.IMPLEMENTATION_CLASS_NAME
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object RequestFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
customFingerprint = { _, classDef ->
|
||||
classDef.type == IMPLEMENTATION_CLASS_NAME
|
||||
}
|
||||
) {
|
||||
const val IMPLEMENTATION_CLASS_NAME = "Lorg/chromium/net/impl/CronetUrlRequest;"
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package app.revanced.patches.youtube.alternativethumbnails.general.fingerprints.cronet.request.callback
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object OnFailureFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf(
|
||||
"Lorg/chromium/net/UrlRequest;",
|
||||
"Lorg/chromium/net/UrlResponseInfo;",
|
||||
"Lorg/chromium/net/CronetException;"
|
||||
),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.name == "onFailed"
|
||||
}
|
||||
)
|
@ -1,14 +1,14 @@
|
||||
package app.revanced.patches.youtube.alternativethumbnails.general.fingerprints
|
||||
package app.revanced.patches.youtube.alternativethumbnails.general.fingerprints.cronet.request.callback
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
// Acts as a parent fingerprint.
|
||||
object CronetURLRequestCallbackOnResponseStartedFingerprint : MethodFingerprint(
|
||||
internal object OnResponseStartedFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;"),
|
||||
parameters = listOf("Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;"),
|
||||
strings = listOf(
|
||||
"Content-Length",
|
||||
"Content-Type",
|
@ -1,13 +1,13 @@
|
||||
package app.revanced.patches.youtube.alternativethumbnails.general.fingerprints
|
||||
package app.revanced.patches.youtube.alternativethumbnails.general.fingerprints.cronet.request.callback
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
object CronetURLRequestCallbackOnSucceededFingerprint : MethodFingerprint(
|
||||
internal object OnSucceededFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;"),
|
||||
parameters = listOf("Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;"),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.name == "onSucceeded"
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string-array name="revanced_alt_thumbnail_type_entries">
|
||||
<item>@string/revanced_alt_thumbnail_type_entry_1</item>
|
||||
<item>@string/revanced_alt_thumbnail_type_entry_2</item>
|
||||
<item>@string/revanced_alt_thumbnail_type_entry_3</item>
|
||||
<item>@string/revanced_alt_thumbnail_stills_time_entry_1</item>
|
||||
<item>@string/revanced_alt_thumbnail_stills_time_entry_2</item>
|
||||
<item>@string/revanced_alt_thumbnail_stills_time_entry_3</item>
|
||||
</string-array>
|
||||
<string-array name="revanced_alt_thumbnail_type_entry_values">
|
||||
<string-array name="revanced_alt_thumbnail_stills_time_entry_values">
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
|
@ -8,21 +8,42 @@
|
||||
|
||||
<string name="revanced_ads">Ads</string>
|
||||
<string name="revanced_alt_thumbnails">Alternative thumbnails</string>
|
||||
<string name="revanced_alt_thumbnail_about_summary">A feature that replaced default video thumbnails with Alternative ones to reduce sensationalism.</string>
|
||||
<string name="revanced_alt_thumbnail_about_title">About</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_summary_off">Thumbnails is generated without external API.</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_summary_on">Thumbnails is generated using DeArrow API.</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_title">Using DeArrow API</string>
|
||||
<string name="revanced_alt_thumbnail_enabled_summary_off">Original YouTube thumbnails shown.</string>
|
||||
<string name="revanced_alt_thumbnail_enabled_summary_on">YouTube thumbnails replaced with Alternative ones.</string>
|
||||
<string name="revanced_alt_thumbnail_enabled_title">Enable alternative thumbnails</string>
|
||||
<string name="revanced_alt_thumbnail_skip_checking_summary_off">Thumbnails will be checked if exist or not before replacing.</string>
|
||||
<string name="revanced_alt_thumbnail_skip_checking_summary_on">Thumbnails will load faster, but some video will show blank thumbnails.</string>
|
||||
<string name="revanced_alt_thumbnail_skip_checking_title">Skip checking for thumbnails</string>
|
||||
<string name="revanced_alt_thumbnail_type_entry_1">Beginning of video</string>
|
||||
<string name="revanced_alt_thumbnail_type_entry_2">Middle of video</string>
|
||||
<string name="revanced_alt_thumbnail_type_entry_3">End of video</string>
|
||||
<string name="revanced_alt_thumbnail_type_title">Video time to take the still from</string>
|
||||
<string name="revanced_alt_thumbnail_about_status_dearrow">"Showing DeArrow thumbnails.
|
||||
If a video has no DeArrow thumbnails then the original YouTube thumbnails are shown."</string>
|
||||
<string name="revanced_alt_thumbnail_about_status_dearrow_stills">"Showing DeArrow thumbnails.
|
||||
If a video has no DeArrow thumbnails then still video captures are shown."</string>
|
||||
<string name="revanced_alt_thumbnail_about_status_disabled">Showing original YouTube thumbnails.</string>
|
||||
<string name="revanced_alt_thumbnail_about_status_stills">Showing still video captures.</string>
|
||||
<string name="revanced_alt_thumbnail_about_title">Thumbnails in use</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_about_summary">"DeArrow provides crowd sourced thumbnails for YouTube videos. These thumbnails are often more relevant than those provided by YouTube. If enabled, video URLs will be sent to the API server and no other data is sent.
|
||||
|
||||
Tap here to learn more about DeArrow."</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_about_title">About DeArrow</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_api_url_summary">"The URL of the DeArrow thumbnail cache endpoint. Do not change this unless you know what you're doing."</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_api_url_title">DeArrow API endpoint</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_off">Toast not shown if DeArrow is not available.</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_on">Toast shown if DeArrow is not available.</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_connection_toast_title">Show toast if API is not available</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_error">DeArrow temporarily not available. (status code: %s)</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_error_generic">DeArrow temporarily not available.</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_summary_off">Not using DeArrow.</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_summary_on">Using DeArrow.</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_title">Enable DeArrow</string>
|
||||
<string name="revanced_alt_thumbnail_preference_screen_summary">Video thumbnail settings.</string>
|
||||
<string name="revanced_alt_thumbnail_preference_screen_title">Alternative thumbnails</string>
|
||||
<string name="revanced_alt_thumbnail_stills">Still video captures</string>
|
||||
<string name="revanced_alt_thumbnail_stills_about_summary">Still captures are taken from the beginning / middle / end of each video. These images are built into YouTube and no external API is used.</string>
|
||||
<string name="revanced_alt_thumbnail_stills_about_title">About still video captures</string>
|
||||
<string name="revanced_alt_thumbnail_stills_fast_summary_off">Using high quality still captures.</string>
|
||||
<string name="revanced_alt_thumbnail_stills_fast_summary_on">Using medium quality still captures. Thumbnails will load faster, but live streams, unreleased, or very old videos may show blank thumbnails.</string>
|
||||
<string name="revanced_alt_thumbnail_stills_fast_title">Use fast still captures</string>
|
||||
<string name="revanced_alt_thumbnail_stills_summary_off">Not using YouTube video still captures.</string>
|
||||
<string name="revanced_alt_thumbnail_stills_summary_on">Using YouTube video still captures.</string>
|
||||
<string name="revanced_alt_thumbnail_stills_time_entry_1">Beginning of video</string>
|
||||
<string name="revanced_alt_thumbnail_stills_time_entry_2">Middle of video</string>
|
||||
<string name="revanced_alt_thumbnail_stills_time_entry_3">End of video</string>
|
||||
<string name="revanced_alt_thumbnail_stills_time_title">Video time to take the still from</string>
|
||||
<string name="revanced_alt_thumbnail_stills_title">Enable still video captures</string>
|
||||
<string name="revanced_append_time_stamp_information_summary_off">Append time stamp information is disabled.</string>
|
||||
<string name="revanced_append_time_stamp_information_summary_on">Append time stamp information is enabled.</string>
|
||||
<string name="revanced_append_time_stamp_information_title">Append time stamp information</string>
|
||||
|
@ -5,6 +5,8 @@
|
||||
<string name="pref_app_language_dialog_message_no_lang_name">This will change the language used in the app including buttons, text and dialogs, but will not change the language of ReVanced Extended settings.</string>
|
||||
<string name="pref_app_language_system_default">System default</string>
|
||||
|
||||
<string name="revanced_alt_thumbnail_dearrow">DeArrow</string>
|
||||
|
||||
<string name="revanced_extended_settings_title">ReVanced Extended</string>
|
||||
|
||||
<string name="revanced_hide_account_menu_filter_strings_summary">@string/revanced_custom_filter_strings_summary</string>
|
||||
|
@ -32,11 +32,19 @@
|
||||
<!-- PREFERENCE: ALTERNATIVE_THUMBNAILS_SETTINGS
|
||||
<PreferenceScreen android:title="@string/revanced_alt_thumbnails" android:key="alt_thumbnails">
|
||||
<Preference android:title=" " android:selectable="false" android:summary="@string/revanced_alt_thumbnails" />
|
||||
<SwitchPreference android:title="@string/revanced_alt_thumbnail_enabled_title" android:key="revanced_alt_thumbnail_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_alt_thumbnail_enabled_summary_on" android:summaryOff="@string/revanced_alt_thumbnail_enabled_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_alt_thumbnail_dearrow_title" android:key="revanced_alt_thumbnail_dearrow" android:defaultValue="false" android:summaryOn="@string/revanced_alt_thumbnail_dearrow_summary_on" android:summaryOff="@string/revanced_alt_thumbnail_dearrow_summary_off" />
|
||||
<ListPreference android:title="@string/revanced_alt_thumbnail_type_title" android:key="revanced_alt_thumbnail_type" android:entries="@array/revanced_alt_thumbnail_type_entries" android:defaultValue="1" android:entryValues="@array/revanced_alt_thumbnail_type_entry_values" />
|
||||
<SwitchPreference android:title="@string/revanced_alt_thumbnail_skip_checking_title" android:key="revanced_alt_thumbnail_skip_checking" android:defaultValue="false" android:summaryOn="@string/revanced_alt_thumbnail_skip_checking_summary_on" android:summaryOff="@string/revanced_alt_thumbnail_skip_checking_summary_off" />
|
||||
<Preference android:title="@string/revanced_alt_thumbnail_about_title" android:selectable="false" android:summary="@string/revanced_alt_thumbnail_about_summary" />
|
||||
<app.revanced.integrations.settingsmenu.AlternativeThumbnailsStatusPreference android:title="@string/revanced_alt_thumbnail_about_title" />
|
||||
|
||||
<Preference android:title=" " android:selectable="false" android:summary="@string/revanced_alt_thumbnail_dearrow" />
|
||||
<SwitchPreference android:title="@string/revanced_alt_thumbnail_dearrow_title" android:key="revanced_alt_thumbnail_dearrow" android:summaryOn="@string/revanced_alt_thumbnail_dearrow_summary_on" android:summaryOff="@string/revanced_alt_thumbnail_dearrow_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_alt_thumbnail_dearrow_connection_toast_title" android:key="revanced_alt_thumbnail_dearrow_connection_toast" android:summaryOn="@string/revanced_alt_thumbnail_dearrow_connection_toast_summary_on" android:summaryOff="@string/revanced_alt_thumbnail_dearrow_connection_toast_summary_off" />
|
||||
<app.revanced.integrations.settingsmenu.ResettableEditTextPreference android:title="@string/revanced_alt_thumbnail_dearrow_api_url_title" android:key="revanced_alt_thumbnail_dearrow_api_url" android:summary="@string/revanced_alt_thumbnail_dearrow_api_url_summary" android:inputType="text" />
|
||||
<app.revanced.integrations.settingsmenu.AlternativeThumbnailsAboutDeArrowPreference android:title="@string/revanced_alt_thumbnail_dearrow_about_title" android:selectable="true" android:summary="@string/revanced_alt_thumbnail_dearrow_about_summary" />
|
||||
|
||||
<Preference android:title=" " android:selectable="false" android:summary="@string/revanced_alt_thumbnail_stills" />
|
||||
<SwitchPreference android:title="@string/revanced_alt_thumbnail_stills_title" android:key="revanced_alt_thumbnail_stills" android:summaryOn="@string/revanced_alt_thumbnail_stills_summary_on" android:summaryOff="@string/revanced_alt_thumbnail_stills_summary_off" />
|
||||
<ListPreference android:entries="@array/revanced_alt_thumbnail_type_entries" android:title="@string/revanced_alt_thumbnail_stills_time_title" android:key="revanced_alt_thumbnail_stills_time" android:entryValues="@array/revanced_alt_thumbnail_stills_time_entry_values" />
|
||||
<SwitchPreference android:title="@string/revanced_alt_thumbnail_stills_fast_title" android:key="revanced_alt_thumbnail_stills_fast" android:summaryOn="@string/revanced_alt_thumbnail_stills_fast_summary_on" android:summaryOff="@string/revanced_alt_thumbnail_stills_fast_summary_off" />
|
||||
<Preference android:title="@string/revanced_alt_thumbnail_stills_about_title" android:selectable="true" android:summary="@string/revanced_alt_thumbnail_stills_about_summary" />
|
||||
</PreferenceScreen>PREFERENCE: ALTERNATIVE_THUMBNAILS_SETTINGS -->
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user