feat: Use modern style settings dialogs (#5109)
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
co-authored by
LisoUseInAIKyrios
parent
9e30c34e74
commit
a426e2af50
+2
-8
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.idaustria.detection.signature
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
val spoofSignaturePatch = bytecodePatch(
|
||||
@@ -24,12 +24,6 @@ val spoofSignaturePatch = bytecodePatch(
|
||||
"77ef1be61b2c01ebdabddcbf53cc4b6fd9a3c445606ee77b3758162c80ad8f8137b3c6864e92db904807dcb2be9d7717dd21" +
|
||||
"bf42c121d620ddfb7914f7a95c713d9e1c1b7bdb4a03d618e40cf7e9e235c0b5687e03b7ab3,publicExponent=10001}"
|
||||
|
||||
spoofSignatureFingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "$expectedSignature"
|
||||
return-object v0
|
||||
""",
|
||||
)
|
||||
spoofSignatureFingerprint.method.returnEarly(expectedSignature)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.nunl.firebase
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
val spoofCertificatePatch = bytecodePatch(
|
||||
@@ -12,13 +12,7 @@ val spoofCertificatePatch = bytecodePatch(
|
||||
|
||||
execute {
|
||||
getFingerprintHashForPackageFingerprints.forEach { fingerprint ->
|
||||
fingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "eae41fc018df2731a9b6ae1ac327da44a288667b"
|
||||
return-object v0
|
||||
""",
|
||||
)
|
||||
fingerprint.method.returnEarly("eae41fc018df2731a9b6ae1ac327da44a288667b")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-8
@@ -1,8 +1,8 @@
|
||||
package app.revanced.patches.photomath.detection.deviceid
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.photomath.detection.signature.signatureDetectionPatch
|
||||
import app.revanced.util.returnEarly
|
||||
import kotlin.random.Random
|
||||
|
||||
@Suppress("unused")
|
||||
@@ -15,12 +15,6 @@ val getDeviceIdPatch = bytecodePatch(
|
||||
compatibleWith("com.microblink.photomath")
|
||||
|
||||
execute {
|
||||
getDeviceIdFingerprint.method.replaceInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "${Random.nextLong().toString(16)}"
|
||||
return-object v0
|
||||
""",
|
||||
)
|
||||
getDeviceIdFingerprint.method.returnEarly(Random.nextLong().toString(16))
|
||||
}
|
||||
}
|
||||
|
||||
+2
-7
@@ -3,6 +3,7 @@ package app.revanced.patches.piccomafr.misc
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.stringOption
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
val spoofAndroidDeviceIdPatch = bytecodePatch(
|
||||
@@ -39,12 +40,6 @@ val spoofAndroidDeviceIdPatch = bytecodePatch(
|
||||
) { it!!.matches("[A-Fa-f0-9]{16}".toRegex()) }
|
||||
|
||||
execute {
|
||||
getAndroidIdFingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "$androidDeviceId"
|
||||
return-object v0
|
||||
""",
|
||||
)
|
||||
getAndroidIdFingerprint.method.returnEarly(androidDeviceId!!)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-8
@@ -1,9 +1,9 @@
|
||||
package app.revanced.patches.reddit.customclients.boostforreddit.api
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patches.reddit.customclients.spoofClientPatch
|
||||
import app.revanced.util.returnEarly
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
val spoofClientPatch = spoofClientPatch(redirectUri = "http://rubenmayayo.com") { clientIdOption ->
|
||||
@@ -14,13 +14,7 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "http://rubenmayayo.com")
|
||||
execute {
|
||||
// region Patch client id.
|
||||
|
||||
getClientIdFingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "$clientId"
|
||||
return-object v0
|
||||
""",
|
||||
)
|
||||
getClientIdFingerprint.method.returnEarly(clientId!!)
|
||||
|
||||
// endregion
|
||||
|
||||
|
||||
+3
-16
@@ -1,9 +1,8 @@
|
||||
package app.revanced.patches.reddit.customclients.joeyforreddit.api
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
|
||||
import app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.disablePiracyDetectionPatch
|
||||
import app.revanced.patches.reddit.customclients.spoofClientPatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
val spoofClientPatch = spoofClientPatch(redirectUri = "https://127.0.0.1:65023/authorize_callback") { clientIdOption ->
|
||||
dependsOn(disablePiracyDetectionPatch)
|
||||
@@ -19,13 +18,7 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "https://127.0.0.1:65023/a
|
||||
execute {
|
||||
// region Patch client id.
|
||||
|
||||
getClientIdFingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "$clientId"
|
||||
return-object v0
|
||||
""",
|
||||
)
|
||||
getClientIdFingerprint.method.returnEarly(clientId!!)
|
||||
|
||||
// endregion
|
||||
|
||||
@@ -35,13 +28,7 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "https://127.0.0.1:65023/a
|
||||
val randomName = (0..100000).random()
|
||||
val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)"
|
||||
|
||||
authUtilityUserAgentFingerprint.method.replaceInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "$userAgent"
|
||||
return-object v0
|
||||
""",
|
||||
)
|
||||
authUtilityUserAgentFingerprint.method.returnEarly(userAgent)
|
||||
|
||||
// endregion
|
||||
}
|
||||
|
||||
+2
-8
@@ -2,12 +2,12 @@ package app.revanced.patches.reddit.customclients.redditisfun.api
|
||||
|
||||
import app.revanced.patcher.Fingerprint
|
||||
import app.revanced.patcher.Match
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patches.reddit.customclients.spoofClientPatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.returnEarly
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.StringReference
|
||||
|
||||
@@ -54,13 +54,7 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "redditisfun://auth") { cl
|
||||
val randomName = (0..100000).random()
|
||||
val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)"
|
||||
|
||||
getUserAgentFingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "$userAgent"
|
||||
return-object v0
|
||||
""",
|
||||
)
|
||||
getUserAgentFingerprint.method.returnEarly(userAgent)
|
||||
|
||||
// endregion
|
||||
|
||||
|
||||
+2
-8
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.reddit.customclients.slide.api
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patches.reddit.customclients.spoofClientPatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
val spoofClientPatch = spoofClientPatch(redirectUri = "http://www.ccrama.me") { clientIdOption ->
|
||||
compatibleWith("me.ccrama.redditslide")
|
||||
@@ -9,12 +9,6 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "http://www.ccrama.me") {
|
||||
val clientId by clientIdOption
|
||||
|
||||
execute {
|
||||
getClientIdFingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "$clientId"
|
||||
return-object v0
|
||||
""",
|
||||
)
|
||||
getClientIdFingerprint.method.returnEarly(clientId!!)
|
||||
}
|
||||
}
|
||||
|
||||
+12
-21
@@ -1,14 +1,14 @@
|
||||
package app.revanced.patches.reddit.customclients.sync.syncforreddit.api
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patches.reddit.customclients.spoofClientPatch
|
||||
import app.revanced.patches.reddit.customclients.sync.detection.piracy.disablePiracyDetectionPatch
|
||||
import app.revanced.util.returnEarly
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.StringReference
|
||||
import java.util.*
|
||||
import java.util.Base64
|
||||
|
||||
val spoofClientPatch = spoofClientPatch(
|
||||
redirectUri = "http://redditsync/auth",
|
||||
@@ -28,13 +28,8 @@ val spoofClientPatch = spoofClientPatch(
|
||||
|
||||
getBearerTokenFingerprint.match(getAuthorizationStringFingerprint.originalClassDef).method.apply {
|
||||
val auth = Base64.getEncoder().encodeToString("$clientId:".toByteArray(Charsets.UTF_8))
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "Basic $auth"
|
||||
return-object v0
|
||||
""",
|
||||
)
|
||||
returnEarly("Basic $auth")
|
||||
|
||||
val occurrenceIndex =
|
||||
getAuthorizationStringFingerprint.stringMatches!!.first().index
|
||||
|
||||
@@ -63,23 +58,19 @@ val spoofClientPatch = spoofClientPatch(
|
||||
val randomName = (0..100000).random()
|
||||
val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)"
|
||||
|
||||
getUserAgentFingerprint.method.replaceInstruction(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "$userAgent"
|
||||
return-object v0
|
||||
""",
|
||||
)
|
||||
getUserAgentFingerprint.method.returnEarly(userAgent)
|
||||
|
||||
// endregion
|
||||
|
||||
// region Patch Imgur API URL.
|
||||
|
||||
val apiUrlIndex = imgurImageAPIFingerprint.stringMatches!!.first().index
|
||||
imgurImageAPIFingerprint.method.replaceInstruction(
|
||||
apiUrlIndex,
|
||||
"const-string v1, \"https://api.imgur.com/3/image\"",
|
||||
)
|
||||
imgurImageAPIFingerprint.let {
|
||||
val apiUrlIndex = it.stringMatches!!.first().index
|
||||
it.method.replaceInstruction(
|
||||
apiUrlIndex,
|
||||
"const-string v1, \"https://api.imgur.com/3/image\"",
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
||||
|
||||
+1
-1
@@ -84,7 +84,7 @@ fun checkEnvironmentPatch(
|
||||
|
||||
fun invokeCheck() = mainActivityOnCreateFingerprint.method.addInstruction(
|
||||
0,
|
||||
"invoke-static/range { p0 .. p0 },$EXTENSION_CLASS_DESCRIPTOR->check(Landroid/app/Activity;)V",
|
||||
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->check(Landroid/app/Activity;)V",
|
||||
)
|
||||
|
||||
setPatchInfo()
|
||||
|
||||
+2
-9
@@ -3,11 +3,11 @@ package app.revanced.patches.shared.misc.extension
|
||||
import app.revanced.patcher.Fingerprint
|
||||
import app.revanced.patcher.FingerprintBuilder
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.returnEarly
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import java.net.URLDecoder
|
||||
import java.util.jar.JarFile
|
||||
@@ -80,14 +80,7 @@ fun sharedExtensionPatch(
|
||||
}
|
||||
|
||||
val manifestValue = getPatchesManifestEntry("Version")
|
||||
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "$manifestValue"
|
||||
return-object v0
|
||||
""",
|
||||
)
|
||||
returnEarly(manifestValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package app.revanced.patches.shared.misc.settings
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patches.shared.misc.extension.EXTENSION_CLASS_DESCRIPTOR
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val themeLightColorResourceNameFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||
returns("Ljava/lang/String;")
|
||||
parameters()
|
||||
custom { method, classDef ->
|
||||
method.name == "getThemeLightColorResourceName" && classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
||||
}
|
||||
}
|
||||
|
||||
internal val themeDarkColorResourceNameFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||
returns("Ljava/lang/String;")
|
||||
parameters()
|
||||
custom { method, classDef ->
|
||||
method.name == "getThemeDarkColorResourceName" && classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.revanced.patches.shared.misc.settings
|
||||
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patches.all.misc.resources.addResource
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
@@ -13,6 +14,7 @@ import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.copyResources
|
||||
import app.revanced.util.getNode
|
||||
import app.revanced.util.insertFirst
|
||||
import app.revanced.util.returnEarly
|
||||
import org.w3c.dom.Node
|
||||
|
||||
// TODO: Delete this on next major version bump.
|
||||
@@ -22,6 +24,30 @@ fun settingsPatch (
|
||||
preferences: Set<BasePreference>,
|
||||
) = settingsPatch(listOf(rootPreference), preferences)
|
||||
|
||||
private var themeForegroundColor : String? = null
|
||||
private var themeBackgroundColor : String? = null
|
||||
|
||||
/**
|
||||
* Sets the default theme colors used in various ReVanced specific settings menus.
|
||||
* By default these colors are white and black, but instead can be set to the
|
||||
* same color the target app uses for it's own settings.
|
||||
*/
|
||||
fun overrideThemeColors(foregroundColor: String, backgroundColor: String) {
|
||||
themeForegroundColor = foregroundColor
|
||||
themeBackgroundColor = backgroundColor
|
||||
}
|
||||
|
||||
private val settingsColorPatch = bytecodePatch {
|
||||
finalize {
|
||||
if (themeForegroundColor != null) {
|
||||
themeLightColorResourceNameFingerprint.method.returnEarly(themeForegroundColor!!)
|
||||
}
|
||||
if (themeBackgroundColor != null) {
|
||||
themeDarkColorResourceNameFingerprint.method.returnEarly(themeBackgroundColor!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A resource patch that adds settings to a settings fragment.
|
||||
*
|
||||
@@ -33,12 +59,28 @@ fun settingsPatch (
|
||||
rootPreferences: List<Pair<BasePreference, String>>? = null,
|
||||
preferences: Set<BasePreference>,
|
||||
) = resourcePatch {
|
||||
dependsOn(addResourcesPatch)
|
||||
dependsOn(addResourcesPatch, settingsColorPatch)
|
||||
|
||||
execute {
|
||||
copyResources(
|
||||
"settings",
|
||||
ResourceGroup("xml", "revanced_prefs.xml", "revanced_prefs_icons.xml"),
|
||||
ResourceGroup("drawable",
|
||||
// CustomListPreference resources.
|
||||
"revanced_ic_dialog_alert.xml",
|
||||
"revanced_settings_arrow_time.xml",
|
||||
"revanced_settings_circle_background.xml",
|
||||
"revanced_settings_cursor.xml",
|
||||
"revanced_settings_custom_checkmark.xml",
|
||||
"revanced_settings_search_icon.xml",
|
||||
"revanced_settings_toolbar_arrow_left.xml",
|
||||
),
|
||||
ResourceGroup("layout",
|
||||
"revanced_custom_list_item_checked.xml",
|
||||
// Color picker.
|
||||
"revanced_color_dot_widget.xml",
|
||||
"revanced_color_picker.xml",
|
||||
)
|
||||
)
|
||||
|
||||
addResources("shared", "misc.settings.settingsResourcePatch")
|
||||
|
||||
+5
-3
@@ -12,7 +12,7 @@ import org.w3c.dom.Document
|
||||
* @param summaryKey The preference summary key.
|
||||
* @param icon The preference icon resource name.
|
||||
* @param layout Layout declaration.
|
||||
* @param tag The preference tag.
|
||||
* @param tag The preference class type.
|
||||
* @param entriesKey The entries array key.
|
||||
* @param entryValuesKey The entry values array key.
|
||||
*/
|
||||
@@ -20,10 +20,12 @@ import org.w3c.dom.Document
|
||||
class ListPreference(
|
||||
key: String? = null,
|
||||
titleKey: String = "${key}_title",
|
||||
summaryKey: String? = "${key}_summary",
|
||||
/** Summary key is ignored and will be removed soon */
|
||||
//@Deprecated
|
||||
summaryKey: String? = null,
|
||||
icon: String? = null,
|
||||
layout: String? = null,
|
||||
tag: String = "ListPreference",
|
||||
tag: String = "app.revanced.extension.shared.settings.preference.CustomDialogListPreference",
|
||||
val entriesKey: String? = "${key}_entries",
|
||||
val entryValuesKey: String? = "${key}_entry_values"
|
||||
) : BasePreference(key, titleKey, summaryKey, icon, layout, tag) {
|
||||
|
||||
@@ -25,7 +25,7 @@ val embeddedAdsPatch = bytecodePatch(
|
||||
addResources("twitch", "ad.embedded.embeddedAdsPatch")
|
||||
|
||||
PreferenceScreen.ADS.SURESTREAM.addPreferences(
|
||||
ListPreference("revanced_block_embedded_ads", summaryKey = null),
|
||||
ListPreference("revanced_block_embedded_ads"),
|
||||
)
|
||||
|
||||
// Inject OkHttp3 application interceptor
|
||||
|
||||
+1
-4
@@ -34,10 +34,7 @@ val showDeletedMessagesPatch = bytecodePatch(
|
||||
addResources("twitch", "chat.antidelete.showDeletedMessagesPatch")
|
||||
|
||||
PreferenceScreen.CHAT.GENERAL.addPreferences(
|
||||
ListPreference(
|
||||
key = "revanced_show_deleted_messages",
|
||||
summaryKey = null,
|
||||
),
|
||||
ListPreference("revanced_show_deleted_messages")
|
||||
)
|
||||
|
||||
// Spoiler mode: Force set hasModAccess member to true in constructor
|
||||
|
||||
+2
-8
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.warnwetter.misc.firebasegetcert
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
val firebaseGetCertPatch = bytecodePatch(
|
||||
description = "Spoofs the X-Android-Cert header.",
|
||||
@@ -10,13 +10,7 @@ val firebaseGetCertPatch = bytecodePatch(
|
||||
|
||||
execute {
|
||||
listOf(getRegistrationCertFingerprint, getMessagingCertFingerprint).forEach { match ->
|
||||
match.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "0799DDF0414D3B3475E88743C91C0676793ED450"
|
||||
return-object v0
|
||||
""",
|
||||
)
|
||||
match.method.returnEarly("0799DDF0414D3B3475E88743C91C0676793ED450")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-8
@@ -11,10 +11,14 @@ import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPref
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
||||
import app.revanced.patches.youtube.misc.playercontrols.*
|
||||
import app.revanced.patches.youtube.misc.playercontrols.addBottomControl
|
||||
import app.revanced.patches.youtube.misc.playercontrols.initializeBottomControl
|
||||
import app.revanced.patches.youtube.misc.playercontrols.injectVisibilityCheckCall
|
||||
import app.revanced.patches.youtube.misc.playercontrols.playerControlsPatch
|
||||
import app.revanced.patches.youtube.misc.playercontrols.playerControlsResourcePatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.shared.mainActivityFingerprint
|
||||
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
|
||||
import app.revanced.patches.youtube.video.information.videoInformationPatch
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.copyResources
|
||||
@@ -83,12 +87,10 @@ val downloadsPatch = bytecodePatch(
|
||||
injectVisibilityCheckCall(BUTTON_DESCRIPTOR)
|
||||
|
||||
// Main activity is used to launch downloader intent.
|
||||
mainActivityFingerprint.method.apply {
|
||||
addInstruction(
|
||||
implementation!!.instructions.lastIndex,
|
||||
"invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->activityCreated(Landroid/app/Activity;)V",
|
||||
)
|
||||
}
|
||||
mainActivityOnCreateFingerprint.method.addInstruction(
|
||||
1,
|
||||
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->activityCreated(Landroid/app/Activity;)V"
|
||||
)
|
||||
|
||||
offlineVideoEndpointFingerprint.method.apply {
|
||||
addInstructionsWithLabels(
|
||||
|
||||
+3
-6
@@ -14,7 +14,7 @@ import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_43_or_greater
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.shared.mainActivityFingerprint
|
||||
import app.revanced.patches.youtube.shared.mainActivityConstructorFingerprint
|
||||
import app.revanced.util.*
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
@@ -43,10 +43,7 @@ private val swipeControlsResourcePatch = resourcePatch {
|
||||
SwitchPreference("revanced_swipe_haptic_feedback"),
|
||||
SwitchPreference("revanced_swipe_save_and_restore_brightness"),
|
||||
SwitchPreference("revanced_swipe_lowest_value_enable_auto_brightness"),
|
||||
ListPreference(
|
||||
"revanced_swipe_overlay_style",
|
||||
summaryKey = null,
|
||||
),
|
||||
ListPreference("revanced_swipe_overlay_style"),
|
||||
TextPreference("revanced_swipe_overlay_background_opacity", inputType = InputType.NUMBER),
|
||||
TextPreference("revanced_swipe_overlay_progress_brightness_color",
|
||||
tag = "app.revanced.extension.shared.settings.preference.ColorPickerPreference",
|
||||
@@ -103,7 +100,7 @@ val swipeControlsPatch = bytecodePatch(
|
||||
|
||||
execute {
|
||||
val wrapperClass = swipeControlsHostActivityFingerprint.classDef
|
||||
val targetClass = mainActivityFingerprint.classDef
|
||||
val targetClass = mainActivityConstructorFingerprint.classDef
|
||||
|
||||
// Inject the wrapper class from the extension into the class hierarchy of MainActivity.
|
||||
wrapperClass.setSuperClass(targetClass.superclass)
|
||||
|
||||
+1
-4
@@ -47,10 +47,7 @@ val changeFormFactorPatch = bytecodePatch(
|
||||
addResources("youtube", "layout.formfactor.changeFormFactorPatch")
|
||||
|
||||
PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||
ListPreference(
|
||||
"revanced_change_form_factor",
|
||||
summaryKey = null,
|
||||
)
|
||||
ListPreference("revanced_change_form_factor")
|
||||
)
|
||||
|
||||
hookNavigationButtonCreated(EXTENSION_CLASS_DESCRIPTOR)
|
||||
|
||||
+5
-10
@@ -184,23 +184,18 @@ val miniplayerPatch = bytecodePatch(
|
||||
|
||||
preferences +=
|
||||
if (is_20_03_or_greater) {
|
||||
ListPreference(
|
||||
"revanced_miniplayer_type",
|
||||
summaryKey = null,
|
||||
)
|
||||
ListPreference("revanced_miniplayer_type")
|
||||
} else if (is_19_43_or_greater) {
|
||||
ListPreference(
|
||||
"revanced_miniplayer_type",
|
||||
summaryKey = null,
|
||||
key = "revanced_miniplayer_type",
|
||||
entriesKey = "revanced_miniplayer_type_legacy_19_43_entries",
|
||||
entryValuesKey = "revanced_miniplayer_type_legacy_19_43_entry_values",
|
||||
entryValuesKey = "revanced_miniplayer_type_legacy_19_43_entry_values"
|
||||
)
|
||||
} else {
|
||||
ListPreference(
|
||||
"revanced_miniplayer_type",
|
||||
summaryKey = null,
|
||||
key = "revanced_miniplayer_type",
|
||||
entriesKey = "revanced_miniplayer_type_legacy_19_16_entries",
|
||||
entryValuesKey = "revanced_miniplayer_type_legacy_19_16_entry_values",
|
||||
entryValuesKey = "revanced_miniplayer_type_legacy_19_16_entry_values"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+1
-4
@@ -49,10 +49,7 @@ internal val exitFullscreenPatch = bytecodePatch(
|
||||
addResources("youtube", "layout.player.fullscreen.exitFullscreenPatch")
|
||||
|
||||
PreferenceScreen.PLAYER.addPreferences(
|
||||
ListPreference(
|
||||
"revanced_exit_fullscreen",
|
||||
summaryKey = null,
|
||||
)
|
||||
ListPreference("revanced_exit_fullscreen")
|
||||
)
|
||||
|
||||
autoRepeatFingerprint.match(autoRepeatParentFingerprint.originalClassDef).method.apply {
|
||||
|
||||
+1
-2
@@ -70,8 +70,7 @@ val shortsAutoplayPatch = bytecodePatch(
|
||||
// Main activity is used to check if app is in pip mode.
|
||||
mainActivityOnCreateFingerprint.method.addInstruction(
|
||||
1,
|
||||
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->" +
|
||||
"setMainActivity(Landroid/app/Activity;)V",
|
||||
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->setMainActivity(Landroid/app/Activity;)V",
|
||||
)
|
||||
|
||||
val reelEnumClass = reelEnumConstructorFingerprint.originalClassDef.type
|
||||
|
||||
+1
-5
@@ -79,14 +79,10 @@ val openShortsInRegularPlayerPatch = bytecodePatch(
|
||||
|
||||
PreferenceScreen.SHORTS.addPreferences(
|
||||
if (is_19_46_or_greater) {
|
||||
ListPreference(
|
||||
key = "revanced_shorts_player_type",
|
||||
summaryKey = null,
|
||||
)
|
||||
ListPreference("revanced_shorts_player_type")
|
||||
} else {
|
||||
ListPreference(
|
||||
key = "revanced_shorts_player_type",
|
||||
summaryKey = null,
|
||||
entriesKey = "revanced_shorts_player_type_legacy_entries",
|
||||
entryValuesKey = "revanced_shorts_player_type_legacy_entry_values"
|
||||
)
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ val spoofAppVersionPatch = bytecodePatch(
|
||||
if (is_19_43_or_greater) {
|
||||
ListPreference(
|
||||
key = "revanced_spoof_app_version_target",
|
||||
summaryKey = null,
|
||||
summaryKey = null
|
||||
)
|
||||
} else {
|
||||
ListPreference(
|
||||
|
||||
-1
@@ -53,7 +53,6 @@ val changeStartPagePatch = bytecodePatch(
|
||||
preferences = setOf(
|
||||
ListPreference(
|
||||
key = "revanced_change_start_page",
|
||||
summaryKey = null,
|
||||
tag = "app.revanced.extension.shared.settings.preference.SortedListPreference"
|
||||
),
|
||||
SwitchPreference("revanced_change_start_page_always")
|
||||
|
||||
@@ -24,26 +24,6 @@ internal val lithoThemeFingerprint = fingerprint {
|
||||
}
|
||||
}
|
||||
|
||||
internal val themeHelperDarkColorFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||
returns("Ljava/lang/String;")
|
||||
parameters()
|
||||
custom { method, _ ->
|
||||
method.name == "darkThemeResourceName" &&
|
||||
method.definingClass == "Lapp/revanced/extension/youtube/ThemeHelper;"
|
||||
}
|
||||
}
|
||||
|
||||
internal val themeHelperLightColorFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||
returns("Ljava/lang/String;")
|
||||
parameters()
|
||||
custom { method, _ ->
|
||||
method.name == "lightThemeResourceName" &&
|
||||
method.definingClass == "Lapp/revanced/extension/youtube/ThemeHelper;"
|
||||
}
|
||||
}
|
||||
|
||||
internal const val GRADIENT_LOADING_SCREEN_AB_CONSTANT = 45412406L
|
||||
|
||||
internal val useGradientLoadingScreenFingerprint = fingerprint {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package app.revanced.patches.youtube.layout.theme
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
@@ -8,6 +7,7 @@ import app.revanced.patcher.patch.stringOption
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.settings.overrideThemeColors
|
||||
import app.revanced.patches.shared.misc.settings.preference.BasePreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.InputType
|
||||
import app.revanced.patches.shared.misc.settings.preference.ListPreference
|
||||
@@ -22,16 +22,17 @@ import app.revanced.patches.youtube.misc.playservice.is_19_47_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.util.childElementsSequence
|
||||
import app.revanced.util.forEachChildElement
|
||||
import app.revanced.util.insertLiteralOverride
|
||||
import org.w3c.dom.Element
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/theme/ThemePatch;"
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/theme/ThemePatch;"
|
||||
|
||||
val themePatch = bytecodePatch(
|
||||
name = "Theme",
|
||||
description = "Adds options for theming and applies a custom background theme (dark background theme defaults to amoled black).",
|
||||
description = "Adds options for theming and applies a custom background theme " +
|
||||
"(dark background theme defaults to amoled black).",
|
||||
) {
|
||||
val amoledBlackColor = "@android:color/black"
|
||||
val whiteColor = "@android:color/white"
|
||||
@@ -109,27 +110,23 @@ val themePatch = bytecodePatch(
|
||||
)
|
||||
)
|
||||
|
||||
overrideThemeColors(lightThemeBackgroundColor!!, darkThemeBackgroundColor!!)
|
||||
|
||||
// Edit theme colors via resources.
|
||||
document("res/values/colors.xml").use { document ->
|
||||
|
||||
val resourcesNode = document.getElementsByTagName("resources").item(0) as Element
|
||||
|
||||
val children = resourcesNode.childNodes
|
||||
for (i in 0 until children.length) {
|
||||
val node = children.item(i) as? Element ?: continue
|
||||
resourcesNode.childElementsSequence().forEach { node ->
|
||||
when (node.getAttribute("name")) {
|
||||
"yt_black0", "yt_black1", "yt_black1_opacity95", "yt_black1_opacity98",
|
||||
"yt_black2", "yt_black3", "yt_black4", "yt_status_bar_background_dark",
|
||||
"material_grey_850",
|
||||
-> node.textContent = darkThemeBackgroundColor
|
||||
|
||||
node.textContent =
|
||||
when (node.getAttribute("name")) {
|
||||
"yt_black0", "yt_black1", "yt_black1_opacity95", "yt_black1_opacity98", "yt_black2", "yt_black3",
|
||||
"yt_black4", "yt_status_bar_background_dark", "material_grey_850",
|
||||
-> darkThemeBackgroundColor ?: continue
|
||||
|
||||
"yt_white1", "yt_white1_opacity95", "yt_white1_opacity98",
|
||||
"yt_white2", "yt_white3", "yt_white4",
|
||||
-> lightThemeBackgroundColor ?: continue
|
||||
|
||||
else -> continue
|
||||
}
|
||||
"yt_white1", "yt_white1_opacity95", "yt_white1_opacity98",
|
||||
"yt_white2", "yt_white3", "yt_white4",
|
||||
-> node.textContent = lightThemeBackgroundColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,67 +148,56 @@ val themePatch = bytecodePatch(
|
||||
}
|
||||
}
|
||||
|
||||
val splashBackgroundColor = "revanced_splash_background_color"
|
||||
|
||||
// Add a dynamic background color to the colors.xml file.
|
||||
lightThemeBackgroundColor?.let {
|
||||
addColorResource("res/values/colors.xml", splashBackgroundColor, it)
|
||||
}
|
||||
|
||||
darkThemeBackgroundColor?.let {
|
||||
addColorResource("res/values-night/colors.xml", splashBackgroundColor, it)
|
||||
}
|
||||
val splashBackgroundColorKey = "revanced_splash_background_color"
|
||||
addColorResource("res/values/colors.xml", splashBackgroundColorKey, lightThemeBackgroundColor!!)
|
||||
addColorResource("res/values-night/colors.xml", splashBackgroundColorKey, darkThemeBackgroundColor!!)
|
||||
|
||||
// Edit splash screen files and change the background color,
|
||||
// if the background colors are set.
|
||||
if (darkThemeBackgroundColor != null && lightThemeBackgroundColor != null) {
|
||||
val splashScreenResourceFiles = listOf(
|
||||
"res/drawable/quantum_launchscreen_youtube.xml",
|
||||
"res/drawable-sw600dp/quantum_launchscreen_youtube.xml",
|
||||
)
|
||||
|
||||
splashScreenResourceFiles.forEach editSplashScreen@{ resourceFile ->
|
||||
document(resourceFile).use { document ->
|
||||
document.getElementsByTagName("layer-list").item(0).forEachChildElement { node ->
|
||||
if (node.hasAttribute("android:drawable")) {
|
||||
node.setAttribute("android:drawable", "@color/$splashBackgroundColor")
|
||||
return@editSplashScreen
|
||||
}
|
||||
arrayOf(
|
||||
"res/drawable/quantum_launchscreen_youtube.xml",
|
||||
"res/drawable-sw600dp/quantum_launchscreen_youtube.xml",
|
||||
).forEach editSplashScreen@{ resourceFileName ->
|
||||
document(resourceFileName).use { document ->
|
||||
document.getElementsByTagName("layer-list").item(0).forEachChildElement { node ->
|
||||
if (node.hasAttribute("android:drawable")) {
|
||||
node.setAttribute("android:drawable", "@color/$splashBackgroundColorKey")
|
||||
return@editSplashScreen
|
||||
}
|
||||
|
||||
throw PatchException("Failed to modify launch screen")
|
||||
}
|
||||
}
|
||||
|
||||
// Fix the splash screen dark mode background color.
|
||||
// In 19.32+ the dark mode splash screen is white and fades to black.
|
||||
// Maybe it's a bug in YT, or maybe it intentionally. Who knows.
|
||||
document("res/values-night-v27/styles.xml").use { document ->
|
||||
// Create a night mode specific override for the splash screen background.
|
||||
val style = document.createElement("style")
|
||||
style.setAttribute("name", "Theme.YouTube.Home")
|
||||
style.setAttribute("parent", "@style/Base.V27.Theme.YouTube.Home")
|
||||
|
||||
// Fix status and navigation bar showing white on some Android devices,
|
||||
// such as SDK 28 Android 10 medium tablet.
|
||||
val colorSplashBackgroundColor = "@color/$splashBackgroundColor"
|
||||
arrayOf(
|
||||
"android:navigationBarColor" to colorSplashBackgroundColor,
|
||||
"android:windowBackground" to colorSplashBackgroundColor,
|
||||
"android:colorBackground" to colorSplashBackgroundColor,
|
||||
"colorPrimaryDark" to colorSplashBackgroundColor,
|
||||
"android:windowLightStatusBar" to "false",
|
||||
).forEach { (name, value) ->
|
||||
val styleItem = document.createElement("item")
|
||||
styleItem.setAttribute("name", name)
|
||||
styleItem.textContent = value
|
||||
style.appendChild(styleItem)
|
||||
}
|
||||
|
||||
val resourcesNode = document.getElementsByTagName("resources").item(0) as Element
|
||||
resourcesNode.appendChild(style)
|
||||
throw PatchException("Failed to modify launch screen")
|
||||
}
|
||||
}
|
||||
|
||||
// Fix the splash screen dark mode background color.
|
||||
// In 19.32+ the dark mode splash screen is white and fades to black.
|
||||
// Maybe it's a bug in YT, or maybe it intentionally. Who knows.
|
||||
document("res/values-night-v27/styles.xml").use { document ->
|
||||
// Create a night mode specific override for the splash screen background.
|
||||
val style = document.createElement("style")
|
||||
style.setAttribute("name", "Theme.YouTube.Home")
|
||||
style.setAttribute("parent", "@style/Base.V27.Theme.YouTube.Home")
|
||||
|
||||
// Fix status and navigation bar showing white on some Android devices,
|
||||
// such as SDK 28 Android 10 medium tablet.
|
||||
val colorSplashBackgroundColor = "@color/$splashBackgroundColorKey"
|
||||
arrayOf(
|
||||
"android:navigationBarColor" to colorSplashBackgroundColor,
|
||||
"android:windowBackground" to colorSplashBackgroundColor,
|
||||
"android:colorBackground" to colorSplashBackgroundColor,
|
||||
"colorPrimaryDark" to colorSplashBackgroundColor,
|
||||
"android:windowLightStatusBar" to "false",
|
||||
).forEach { (name, value) ->
|
||||
val styleItem = document.createElement("item")
|
||||
styleItem.setAttribute("name", name)
|
||||
styleItem.textContent = value
|
||||
style.appendChild(styleItem)
|
||||
}
|
||||
|
||||
val resourcesNode = document.getElementsByTagName("resources").item(0) as Element
|
||||
resourcesNode.appendChild(style)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -237,10 +223,7 @@ val themePatch = bytecodePatch(
|
||||
|
||||
if (is_19_47_or_greater) {
|
||||
PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||
ListPreference(
|
||||
key = "splash_screen_animation_style",
|
||||
summaryKey = null
|
||||
)
|
||||
ListPreference("splash_screen_animation_style")
|
||||
)
|
||||
}
|
||||
|
||||
@@ -257,21 +240,6 @@ val themePatch = bytecodePatch(
|
||||
)
|
||||
}
|
||||
|
||||
arrayOf(
|
||||
themeHelperLightColorFingerprint to lightThemeBackgroundColor,
|
||||
themeHelperDarkColorFingerprint to darkThemeBackgroundColor,
|
||||
).forEach { (fingerprint, color) ->
|
||||
fingerprint.method.apply {
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "$color"
|
||||
return-object v0
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
lithoColorOverrideHook(EXTENSION_CLASS_DESCRIPTOR, "getValue")
|
||||
}
|
||||
}
|
||||
|
||||
+11
-16
@@ -50,34 +50,29 @@ val alternativeThumbnailsPatch = bytecodePatch(
|
||||
val values = "revanced_alt_thumbnail_options_entry_values"
|
||||
PreferenceScreen.ALTERNATIVE_THUMBNAILS.addPreferences(
|
||||
ListPreference(
|
||||
"revanced_alt_thumbnail_home",
|
||||
summaryKey = null,
|
||||
key = "revanced_alt_thumbnail_home",
|
||||
entriesKey = entries,
|
||||
entryValuesKey = values,
|
||||
entryValuesKey = values
|
||||
),
|
||||
ListPreference(
|
||||
"revanced_alt_thumbnail_subscription",
|
||||
summaryKey = null,
|
||||
key = "revanced_alt_thumbnail_subscription",
|
||||
entriesKey = entries,
|
||||
entryValuesKey = values,
|
||||
entryValuesKey = values
|
||||
),
|
||||
ListPreference(
|
||||
"revanced_alt_thumbnail_library",
|
||||
summaryKey = null,
|
||||
key = "revanced_alt_thumbnail_library",
|
||||
entriesKey = entries,
|
||||
entryValuesKey = values,
|
||||
entryValuesKey = values
|
||||
),
|
||||
ListPreference(
|
||||
"revanced_alt_thumbnail_player",
|
||||
summaryKey = null,
|
||||
key = "revanced_alt_thumbnail_player",
|
||||
entriesKey = entries,
|
||||
entryValuesKey = values,
|
||||
entryValuesKey = values
|
||||
),
|
||||
ListPreference(
|
||||
"revanced_alt_thumbnail_search",
|
||||
summaryKey = null,
|
||||
key = "revanced_alt_thumbnail_search",
|
||||
entriesKey = entries,
|
||||
entryValuesKey = values,
|
||||
entryValuesKey = values
|
||||
),
|
||||
NonInteractivePreference(
|
||||
"revanced_alt_thumbnail_dearrow_about",
|
||||
@@ -89,7 +84,7 @@ val alternativeThumbnailsPatch = bytecodePatch(
|
||||
TextPreference("revanced_alt_thumbnail_dearrow_api_url"),
|
||||
NonInteractivePreference("revanced_alt_thumbnail_stills_about"),
|
||||
SwitchPreference("revanced_alt_thumbnail_stills_fast"),
|
||||
ListPreference("revanced_alt_thumbnail_stills_time", summaryKey = null),
|
||||
ListPreference("revanced_alt_thumbnail_stills_time"),
|
||||
)
|
||||
|
||||
addImageUrlHook(EXTENSION_CLASS_DESCRIPTOR)
|
||||
|
||||
-9
@@ -4,15 +4,6 @@ import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal val onBackPressedFingerprint = fingerprint {
|
||||
returns("V")
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
opcodes(Opcode.RETURN_VOID)
|
||||
custom { method, classDef ->
|
||||
method.name == "onBackPressed" && classDef.endsWith("MainActivity;")
|
||||
}
|
||||
}
|
||||
|
||||
internal val scrollPositionFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PROTECTED, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
|
||||
+6
-5
@@ -2,6 +2,7 @@ package app.revanced.patches.youtube.misc.fix.backtoexitgesture
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.youtube.shared.mainActivityOnBackPressedFingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
@@ -10,7 +11,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/FixBackToExitGesturePatch;"
|
||||
|
||||
internal val fixBackToExitGesturePatch = bytecodePatch(
|
||||
description = "Fixes the swipe back to exit gesture.",
|
||||
description = "Fixes the swipe back to exit gesture."
|
||||
) {
|
||||
|
||||
execute {
|
||||
@@ -36,12 +37,12 @@ internal val fixBackToExitGesturePatch = bytecodePatch(
|
||||
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->onScrollingViews()V"
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onBackPressedFingerprint.let {
|
||||
it.method.addInstruction(
|
||||
it.patternMatch!!.endIndex,
|
||||
mainActivityOnBackPressedFingerprint.method.apply {
|
||||
val index = indexOfFirstInstructionOrThrow(Opcode.RETURN_VOID)
|
||||
addInstruction(
|
||||
index,
|
||||
"invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->onBackPressed(Landroid/app/Activity;)V"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -42,15 +42,6 @@ internal val initializeButtonsFingerprint = fingerprint {
|
||||
literal { imageOnlyTabResourceId }
|
||||
}
|
||||
|
||||
internal val mainActivityOnBackPressedFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
parameters()
|
||||
custom { method, classDef ->
|
||||
method.name == "onBackPressed" && classDef.endsWith("MainActivity;")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension method, used for callback into to other patches.
|
||||
* Specifically, [navigationButtonsPatch].
|
||||
|
||||
+1
@@ -15,6 +15,7 @@ import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_35_or_greater
|
||||
import app.revanced.patches.youtube.shared.mainActivityOnBackPressedFingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||
|
||||
@@ -3,7 +3,6 @@ package app.revanced.patches.youtube.misc.settings
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val licenseActivityOnCreateFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
@@ -18,13 +17,9 @@ internal val setThemeFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("L")
|
||||
parameters()
|
||||
opcodes(Opcode.RETURN_OBJECT)
|
||||
literal { appearanceStringId }
|
||||
}
|
||||
|
||||
/**
|
||||
* Added in YouTube v19.04.38.
|
||||
*/
|
||||
internal const val CAIRO_CONFIG_LITERAL_VALUE = 45532100L
|
||||
|
||||
internal val cairoFragmentConfigFingerprint = fingerprint {
|
||||
|
||||
+45
-43
@@ -1,9 +1,7 @@
|
||||
package app.revanced.patches.youtube.misc.settings
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
@@ -13,15 +11,32 @@ import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.mapping.get
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||
import app.revanced.patches.shared.misc.settings.preference.*
|
||||
import app.revanced.patches.shared.misc.settings.overrideThemeColors
|
||||
import app.revanced.patches.shared.misc.settings.preference.BasePreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.BasePreferenceScreen
|
||||
import app.revanced.patches.shared.misc.settings.preference.InputType
|
||||
import app.revanced.patches.shared.misc.settings.preference.IntentPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.ListPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceCategory
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
||||
import app.revanced.patches.shared.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.misc.check.checkEnvironmentPatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.fix.playbackspeed.fixPlaybackSpeedWhilePlayingPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.util.*
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.addInstructionsAtControlFlowLabel
|
||||
import app.revanced.util.copyResources
|
||||
import app.revanced.util.copyXmlNode
|
||||
import app.revanced.util.findElementByAttributeValueOrThrow
|
||||
import app.revanced.util.findInstructionIndicesReversedOrThrow
|
||||
import app.revanced.util.inputStreamFromBundledResource
|
||||
import app.revanced.util.insertLiteralOverride
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
||||
@@ -30,7 +45,9 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||
|
||||
// Used by a fingerprint() from SettingsPatch.
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/settings/LicenseActivityHook;"
|
||||
|
||||
internal var appearanceStringId = -1L
|
||||
private set
|
||||
|
||||
@@ -69,13 +86,13 @@ private val settingsResourcePatch = resourcePatch {
|
||||
)
|
||||
|
||||
execute {
|
||||
// Used for a fingerprint from SettingsPatch.
|
||||
appearanceStringId = resourceMappings["string", "app_theme_appearance_dark"]
|
||||
|
||||
// Use same colors as stock YouTube.
|
||||
overrideThemeColors("@color/yt_white1", "@color/yt_black3")
|
||||
|
||||
arrayOf(
|
||||
ResourceGroup("drawable",
|
||||
"revanced_settings_circle_background.xml",
|
||||
"revanced_settings_cursor.xml",
|
||||
"revanced_settings_icon.xml",
|
||||
"revanced_settings_screen_00_about.xml",
|
||||
"revanced_settings_screen_01_ads.xml",
|
||||
@@ -92,11 +109,10 @@ private val settingsResourcePatch = resourcePatch {
|
||||
"revanced_settings_screen_12_video.xml",
|
||||
),
|
||||
ResourceGroup("layout",
|
||||
"revanced_color_dot_widget.xml",
|
||||
"revanced_color_picker.xml",
|
||||
"revanced_preference_with_icon_no_search_result.xml",
|
||||
"revanced_search_suggestion_item.xml",
|
||||
"revanced_settings_with_toolbar.xml"),
|
||||
"revanced_settings_with_toolbar.xml"
|
||||
),
|
||||
ResourceGroup("menu", "revanced_search_menu.xml")
|
||||
).forEach { resourceGroup ->
|
||||
copyResources("settings", resourceGroup)
|
||||
@@ -170,12 +186,6 @@ val settingsPatch = bytecodePatch(
|
||||
checkEnvironmentPatch,
|
||||
)
|
||||
|
||||
val extensionPackage = "app/revanced/extension/youtube"
|
||||
val activityHookClassDescriptor = "L$extensionPackage/settings/LicenseActivityHook;"
|
||||
|
||||
val themeHelperDescriptor = "L$extensionPackage/ThemeHelper;"
|
||||
val setThemeMethodName = "setTheme"
|
||||
|
||||
execute {
|
||||
addResources("youtube", "misc.settings.settingsPatch")
|
||||
|
||||
@@ -185,7 +195,7 @@ val settingsPatch = bytecodePatch(
|
||||
icon = "@drawable/revanced_settings_screen_00_about",
|
||||
layout = "@layout/preference_with_icon",
|
||||
summaryKey = null,
|
||||
tag = "app.revanced.extension.youtube.settings.preference.ReVancedYouTubeAboutPreference",
|
||||
tag = "app.revanced.extension.shared.settings.preference.ReVancedAboutPreference",
|
||||
selectable = true,
|
||||
)
|
||||
|
||||
@@ -210,31 +220,10 @@ val settingsPatch = bytecodePatch(
|
||||
),
|
||||
ListPreference(
|
||||
key = "revanced_language",
|
||||
summaryKey = null,
|
||||
tag = "app.revanced.extension.shared.settings.preference.SortedListPreference"
|
||||
)
|
||||
)
|
||||
|
||||
setThemeFingerprint.method.let { setThemeMethod ->
|
||||
setThemeMethod.implementation!!.instructions.mapIndexedNotNull { i, instruction ->
|
||||
if (instruction.opcode == Opcode.RETURN_OBJECT) i else null
|
||||
}.asReversed().forEach { returnIndex ->
|
||||
// The following strategy is to replace the return instruction with the setTheme instruction,
|
||||
// then add a return instruction after the setTheme instruction.
|
||||
// This is done because the return instruction is a target of another instruction.
|
||||
|
||||
setThemeMethod.apply {
|
||||
// This register is returned by the setTheme method.
|
||||
val register = getInstruction<OneRegisterInstruction>(returnIndex).registerA
|
||||
replaceInstruction(
|
||||
returnIndex,
|
||||
"invoke-static { v$register }, " +
|
||||
"$themeHelperDescriptor->$setThemeMethodName(Ljava/lang/Enum;)V",
|
||||
)
|
||||
addInstruction(returnIndex + 1, "return-object v$register")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Modify the license activity and remove all existing layout code.
|
||||
// Must modify an existing activity and cannot add a new activity to the manifest,
|
||||
@@ -243,9 +232,9 @@ val settingsPatch = bytecodePatch(
|
||||
licenseActivityOnCreateFingerprint.method.addInstructions(
|
||||
1,
|
||||
"""
|
||||
invoke-static { p0 }, $activityHookClassDescriptor->initialize(Landroid/app/Activity;)V
|
||||
invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->initialize(Landroid/app/Activity;)V
|
||||
return-void
|
||||
""",
|
||||
"""
|
||||
)
|
||||
|
||||
// Remove other methods as they will break as the onCreate method is modified above.
|
||||
@@ -267,7 +256,7 @@ val settingsPatch = bytecodePatch(
|
||||
).toMutable().apply {
|
||||
addInstructions(
|
||||
"""
|
||||
invoke-static { p1 }, $activityHookClassDescriptor->getAttachBaseContext(Landroid/content/Context;)Landroid/content/Context;
|
||||
invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->getAttachBaseContext(Landroid/content/Context;)Landroid/content/Context;
|
||||
move-result-object p1
|
||||
invoke-super { p0, p1 }, $superclass->attachBaseContext(Landroid/content/Context;)V
|
||||
return-void
|
||||
@@ -278,10 +267,23 @@ val settingsPatch = bytecodePatch(
|
||||
methods.add(attachBaseContext)
|
||||
}
|
||||
|
||||
// Update shared dark mode status based on YT theme.
|
||||
// This is needed because YT allows forcing light/dark mode
|
||||
// which then differs from the system dark mode status.
|
||||
setThemeFingerprint.method.apply {
|
||||
findInstructionIndicesReversedOrThrow(Opcode.RETURN_OBJECT).forEach { index ->
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
addInstructionsAtControlFlowLabel(
|
||||
index,
|
||||
"invoke-static { v$register }, ${EXTENSION_CLASS_DESCRIPTOR}->updateLightDarkModeStatus(Ljava/lang/Enum;)V",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Add setting to force cairo settings fragment on/off.
|
||||
cairoFragmentConfigFingerprint.method.insertLiteralOverride(
|
||||
CAIRO_CONFIG_LITERAL_VALUE,
|
||||
"$activityHookClassDescriptor->useCairoSettingsFragment(Z)Z"
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->useCairoSettingsFragment(Z)Z"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+1
-5
@@ -48,10 +48,7 @@ val spoofVideoStreamsPatch = spoofVideoStreamsPatch({
|
||||
sorting = PreferenceScreenPreference.Sorting.UNSORTED,
|
||||
preferences = setOf(
|
||||
SwitchPreference("revanced_spoof_video_streams"),
|
||||
ListPreference(
|
||||
"revanced_spoof_video_streams_client_type",
|
||||
summaryKey = null,
|
||||
),
|
||||
ListPreference("revanced_spoof_video_streams_client_type"),
|
||||
NonInteractivePreference(
|
||||
// Requires a key and title but the actual text is chosen at runtime.
|
||||
key = "revanced_spoof_video_streams_about_android",
|
||||
@@ -59,7 +56,6 @@ val spoofVideoStreamsPatch = spoofVideoStreamsPatch({
|
||||
),
|
||||
ListPreference(
|
||||
key = "revanced_spoof_video_streams_language",
|
||||
summaryKey = null,
|
||||
// Language strings are declared in Setting patch.
|
||||
entriesKey = "revanced_language_entries",
|
||||
entryValuesKey = "revanced_language_entry_values",
|
||||
|
||||
@@ -44,11 +44,20 @@ internal val layoutConstructorFingerprint = fingerprint {
|
||||
strings("1.0x")
|
||||
}
|
||||
|
||||
internal val mainActivityFingerprint = fingerprint {
|
||||
internal val mainActivityConstructorFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
parameters()
|
||||
custom { _, classDef ->
|
||||
classDef.endsWith("MainActivity;")
|
||||
classDef.endsWith("/MainActivity;")
|
||||
}
|
||||
}
|
||||
|
||||
internal val mainActivityOnBackPressedFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
parameters()
|
||||
custom { method, classDef ->
|
||||
method.name == "onBackPressed" && classDef.endsWith("/MainActivity;")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +65,7 @@ internal val mainActivityOnCreateFingerprint = fingerprint {
|
||||
returns("V")
|
||||
parameters("Landroid/os/Bundle;")
|
||||
custom { method, classDef ->
|
||||
method.name == "onCreate" && classDef.endsWith("MainActivity;")
|
||||
method.name == "onCreate" && classDef.endsWith("/MainActivity;")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-7
@@ -37,29 +37,25 @@ val rememberVideoQualityPatch = bytecodePatch {
|
||||
settingsMenuVideoQualityGroup.addAll(listOf(
|
||||
ListPreference(
|
||||
key = "revanced_video_quality_default_mobile",
|
||||
summaryKey = null,
|
||||
entriesKey = "revanced_video_quality_default_entries",
|
||||
entryValuesKey = "revanced_video_quality_default_entry_values",
|
||||
entryValuesKey = "revanced_video_quality_default_entry_values"
|
||||
),
|
||||
ListPreference(
|
||||
key = "revanced_video_quality_default_wifi",
|
||||
summaryKey = null,
|
||||
entriesKey = "revanced_video_quality_default_entries",
|
||||
entryValuesKey = "revanced_video_quality_default_entry_values",
|
||||
entryValuesKey = "revanced_video_quality_default_entry_values"
|
||||
),
|
||||
SwitchPreference("revanced_remember_video_quality_last_selected"),
|
||||
|
||||
ListPreference(
|
||||
key = "revanced_shorts_quality_default_mobile",
|
||||
summaryKey = null,
|
||||
entriesKey = "revanced_shorts_quality_default_entries",
|
||||
entryValuesKey = "revanced_shorts_quality_default_entry_values",
|
||||
),
|
||||
ListPreference(
|
||||
key = "revanced_shorts_quality_default_wifi",
|
||||
summaryKey = null,
|
||||
entriesKey = "revanced_shorts_quality_default_entries",
|
||||
entryValuesKey = "revanced_shorts_quality_default_entry_values",
|
||||
entryValuesKey = "revanced_shorts_quality_default_entry_values"
|
||||
),
|
||||
SwitchPreference("revanced_remember_shorts_quality_last_selected")
|
||||
))
|
||||
|
||||
-1
@@ -34,7 +34,6 @@ internal val rememberPlaybackSpeedPatch = bytecodePatch {
|
||||
listOf(
|
||||
ListPreference(
|
||||
key = "revanced_playback_speed_default",
|
||||
summaryKey = null,
|
||||
// Entries and values are set by the extension code based on the actual speeds available.
|
||||
entriesKey = null,
|
||||
entryValuesKey = null,
|
||||
|
||||
@@ -742,16 +742,22 @@ private const val RETURN_TYPE_MISMATCH = "Mismatch between override type and Met
|
||||
*
|
||||
* For methods that return an object or any array type, calling this method with `false`
|
||||
* will force the method to return a `null` value.
|
||||
*
|
||||
* @see returnLate
|
||||
*/
|
||||
fun MutableMethod.returnEarly(value: Boolean = false) {
|
||||
val returnType = returnType.first()
|
||||
check(returnType == 'Z' || (!value && (returnType in setOf('V', 'L', '[')))) { RETURN_TYPE_MISMATCH }
|
||||
check(returnType == 'Z' || (!value && (returnType == 'V' || returnType == 'L' || returnType != '['))) {
|
||||
RETURN_TYPE_MISMATCH
|
||||
}
|
||||
overrideReturnValue(value.toHexString(), false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the first instruction of a method with a constant `Byte` return value.
|
||||
* None of the method code will ever execute.
|
||||
*
|
||||
* @see returnLate
|
||||
*/
|
||||
fun MutableMethod.returnEarly(value: Byte) {
|
||||
check(returnType.first() == 'B') { RETURN_TYPE_MISMATCH }
|
||||
@@ -761,6 +767,8 @@ fun MutableMethod.returnEarly(value: Byte) {
|
||||
/**
|
||||
* Overrides the first instruction of a method with a constant `Short` return value.
|
||||
* None of the method code will ever execute.
|
||||
*
|
||||
* @see returnLate
|
||||
*/
|
||||
fun MutableMethod.returnEarly(value: Short) {
|
||||
check(returnType.first() == 'S') { RETURN_TYPE_MISMATCH }
|
||||
@@ -770,6 +778,8 @@ fun MutableMethod.returnEarly(value: Short) {
|
||||
/**
|
||||
* Overrides the first instruction of a method with a constant `Char` return value.
|
||||
* None of the method code will ever execute.
|
||||
*
|
||||
* @see returnLate
|
||||
*/
|
||||
fun MutableMethod.returnEarly(value: Char) {
|
||||
check(returnType.first() == 'C') { RETURN_TYPE_MISMATCH }
|
||||
@@ -779,6 +789,8 @@ fun MutableMethod.returnEarly(value: Char) {
|
||||
/**
|
||||
* Overrides the first instruction of a method with a constant `Int` return value.
|
||||
* None of the method code will ever execute.
|
||||
*
|
||||
* @see returnLate
|
||||
*/
|
||||
fun MutableMethod.returnEarly(value: Int) {
|
||||
check(returnType.first() == 'I') { RETURN_TYPE_MISMATCH }
|
||||
@@ -788,6 +800,8 @@ fun MutableMethod.returnEarly(value: Int) {
|
||||
/**
|
||||
* Overrides the first instruction of a method with a constant `Long` return value.
|
||||
* None of the method code will ever execute.
|
||||
*
|
||||
* @see returnLate
|
||||
*/
|
||||
fun MutableMethod.returnEarly(value: Long) {
|
||||
check(returnType.first() == 'J') { RETURN_TYPE_MISMATCH }
|
||||
@@ -797,6 +811,8 @@ fun MutableMethod.returnEarly(value: Long) {
|
||||
/**
|
||||
* Overrides the first instruction of a method with a constant `Float` return value.
|
||||
* None of the method code will ever execute.
|
||||
*
|
||||
* @see returnLate
|
||||
*/
|
||||
fun MutableMethod.returnEarly(value: Float) {
|
||||
check(returnType.first() == 'F') { RETURN_TYPE_MISMATCH }
|
||||
@@ -806,12 +822,30 @@ fun MutableMethod.returnEarly(value: Float) {
|
||||
/**
|
||||
* Overrides the first instruction of a method with a constant `Double` return value.
|
||||
* None of the method code will ever execute.
|
||||
*
|
||||
* @see returnLate
|
||||
*/
|
||||
fun MutableMethod.returnEarly(value: Double) {
|
||||
check(returnType.first() == 'J') { RETURN_TYPE_MISMATCH }
|
||||
overrideReturnValue(value.toString(), false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the first instruction of a method with a constant String return value.
|
||||
* None of the method code will ever execute.
|
||||
*
|
||||
* Target method must have return type
|
||||
* Ljava/lang/String; or Ljava/lang/CharSequence;
|
||||
*
|
||||
* @see returnLate
|
||||
*/
|
||||
fun MutableMethod.returnEarly(value: String) {
|
||||
check(returnType == "Ljava/lang/String;" || returnType == "Ljava/lang/CharSequence;") {
|
||||
RETURN_TYPE_MISMATCH
|
||||
}
|
||||
overrideReturnValue(value, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides all return statements with a constant `Boolean` value.
|
||||
* All method code is executed the same as unpatched.
|
||||
@@ -826,7 +860,9 @@ fun MutableMethod.returnLate(value: Boolean) {
|
||||
if (returnType == 'V') {
|
||||
error("Cannot return late for Method of void type")
|
||||
}
|
||||
check(returnType == 'Z' || (!value && returnType in setOf('L', '['))) { RETURN_TYPE_MISMATCH }
|
||||
check(returnType == 'Z' || (!value && (returnType == 'L' || returnType == '['))) {
|
||||
RETURN_TYPE_MISMATCH
|
||||
}
|
||||
|
||||
overrideReturnValue(value.toHexString(), true)
|
||||
}
|
||||
@@ -908,8 +944,29 @@ fun MutableMethod.returnLate(value: Double) {
|
||||
overrideReturnValue(value.toString(), true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides all return statements with a constant String value.
|
||||
* All method code is executed the same as unpatched.
|
||||
*
|
||||
* Target method must have return type
|
||||
* Ljava/lang/String; or Ljava/lang/CharSequence;
|
||||
*
|
||||
* @see returnEarly
|
||||
*/
|
||||
fun MutableMethod.returnLate(value: String) {
|
||||
check(returnType == "Ljava/lang/String;" || returnType == "Ljava/lang/CharSequence;") {
|
||||
RETURN_TYPE_MISMATCH
|
||||
}
|
||||
overrideReturnValue(value, true)
|
||||
}
|
||||
|
||||
private fun MutableMethod.overrideReturnValue(value: String, returnLate: Boolean) {
|
||||
val instructions = when (returnType.first()) {
|
||||
val instructions = if (returnType == "Ljava/lang/String;" || returnType == "Ljava/lang/CharSequence;" ) {
|
||||
"""
|
||||
const-string v0, "$value"
|
||||
return-object v0
|
||||
"""
|
||||
} else when (returnType.first()) {
|
||||
// If return type is an object, always return null.
|
||||
'L', '[' -> {
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user