regex
This commit is contained in:
parent
e192cbae52
commit
466043132a
203 changed files with 1786 additions and 1262 deletions
|
|
@ -1,12 +1,17 @@
|
|||
package app.revanced.patches.com.sbs.ondemand.tv
|
||||
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
||||
internal val BytecodePatchContext.shouldShowAdvertisingTVMethod by gettingFirstMutableMethodDeclaratively {
|
||||
import app.revanced.patcher.returnTypeinternal val BytecodePatchContext.shouldShowAdvertisingTVMethod by gettingFirstMutableMethodDeclaratively {
|
||||
name("getShouldShowAdvertisingTV")
|
||||
definingClass("Lcom/sbs/ondemand/common/InMemoryStorage;")
|
||||
returnType("Z")
|
||||
|
|
@ -16,11 +21,10 @@ internal val BytecodePatchContext.shouldShowPauseAdMethod by gettingFirstMutable
|
|||
name("shouldShowPauseAd")
|
||||
definingClass("Lcom/sbs/ondemand/player/viewmodels/PauseAdController;")
|
||||
returnType("Z")
|
||||
|
||||
}
|
||||
|
||||
internal val BytecodePatchContext.requestAdStreamMethod by gettingFirstMutableMethodDeclaratively {
|
||||
name("requestAdStream\$player_googleStoreTvRelease")
|
||||
definingClass("Lcom/sbs/ondemand/player/viewmodels/AdsController;")
|
||||
returnType("V")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package app.revanced.patches.instagram.feed
|
|||
import app.revanced.patcher.classDef
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
import app.revanced.patches.instagram.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.util.getReference
|
||||
|
|
@ -41,13 +40,13 @@ val `Limit feed to followed profiles` by creatingBytecodePatch(
|
|||
}
|
||||
}
|
||||
|
||||
val initMainFeedRequestFingerprint = fingerprint {
|
||||
val initMainFeedRequestMethod = fingerprint {
|
||||
custom { method, classDef ->
|
||||
method.name == "<init>" &&
|
||||
classDef == mainFeedRequestClassMethod.classDef
|
||||
}
|
||||
}
|
||||
initMainFeedRequestFingerprint.method.apply {
|
||||
initMainFeedRequestMethod.apply {
|
||||
// Finds the instruction where the map is being initialized in the constructor
|
||||
val getHeaderIndex = indexOfFirstInstructionOrThrow {
|
||||
getReference<FieldReference>().let {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
|
||||
package app.revanced.patches.instagram.hide.navigation
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val initializeNavigationButtonsListFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.initializeNavigationButtonsListMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
parameterTypes("Lcom/instagram/common/session/UserSession;", "Z")
|
||||
returnType("Ljava/util/List;")
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package app.revanced.patches.instagram.hide.navigation
|
||||
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.patch.booleanOption
|
||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
import app.revanced.patches.instagram.misc.extension.sharedExtensionPatch
|
||||
|
|
@ -21,7 +20,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR =
|
|||
@Suppress("unused", "ObjectPropertyName")
|
||||
val `Hide navigation buttons` by creatingBytecodePatch(
|
||||
description = "Hides navigation bar buttons, such as the Reels and Create button.",
|
||||
use = false
|
||||
use = false,
|
||||
) {
|
||||
compatibleWith("com.instagram.android"("401.0.0.48.79"))
|
||||
|
||||
|
|
@ -30,53 +29,52 @@ val `Hide navigation buttons` by creatingBytecodePatch(
|
|||
val hideHome by booleanOption(
|
||||
default = false,
|
||||
name = "Hide Home",
|
||||
description = "Permanently hides the Home button. App starts at next available tab." // On the "homecoming" / current instagram layout.
|
||||
description = "Permanently hides the Home button. App starts at next available tab.", // On the "homecoming" / current instagram layout.
|
||||
)
|
||||
|
||||
val hideReels by booleanOption(
|
||||
default = true,
|
||||
name = "Hide Reels",
|
||||
description = "Permanently hides the Reels button."
|
||||
description = "Permanently hides the Reels button.",
|
||||
)
|
||||
|
||||
val hideDirect by booleanOption(
|
||||
default = false,
|
||||
name = "Hide Direct",
|
||||
description = "Permanently hides the Direct button."
|
||||
description = "Permanently hides the Direct button.",
|
||||
)
|
||||
|
||||
val hideSearch by booleanOption(
|
||||
default = false,
|
||||
name = "Hide Search",
|
||||
description = "Permanently hides the Search button."
|
||||
description = "Permanently hides the Search button.",
|
||||
)
|
||||
|
||||
val hideProfile by booleanOption(
|
||||
default = false,
|
||||
name = "Hide Profile",
|
||||
description = "Permanently hides the Profile button."
|
||||
description = "Permanently hides the Profile button.",
|
||||
)
|
||||
|
||||
val hideCreate by booleanOption(
|
||||
default = true,
|
||||
name = "Hide Create",
|
||||
description = "Permanently hides the Create button."
|
||||
description = "Permanently hides the Create button.",
|
||||
)
|
||||
|
||||
apply {
|
||||
if (!hideHome!! && !hideReels!! && !hideDirect!! && !hideSearch!! && !hideProfile!! && !hideCreate!!) {
|
||||
return@apply Logger.getLogger(this::class.java.name).warning(
|
||||
"No hide navigation buttons options are enabled. No changes made."
|
||||
"No hide navigation buttons options are enabled. No changes made.",
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// Get the field name which contains the name of the enum for the navigation button
|
||||
// ("fragment_clips", "fragment_share", ...)
|
||||
val navigationButtonsEnumInitFingerprint = fingerprint {
|
||||
custom { method, classDef ->
|
||||
method.name == "<init>"
|
||||
&& classDef == navigationButtonsEnumClassDef.classDef
|
||||
method.name == "<init>" &&
|
||||
classDef == navigationButtonsEnumClassDef.classDef
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -84,68 +82,65 @@ val `Hide navigation buttons` by creatingBytecodePatch(
|
|||
with(navigationButtonsEnumInitFingerprint.method) {
|
||||
enumNameField = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.IPUT_OBJECT &&
|
||||
(this as TwoRegisterInstruction).registerA == 2 // p2 register.
|
||||
(this as TwoRegisterInstruction).registerA == 2 // p2 register.
|
||||
}.let {
|
||||
getInstruction(it).getReference<FieldReference>()!!.name
|
||||
}
|
||||
}
|
||||
|
||||
initializeNavigationButtonsListFingerprint.method.apply {
|
||||
initializeNavigationButtonsListMethod.apply {
|
||||
val returnIndex = indexOfFirstInstructionOrThrow(Opcode.RETURN_OBJECT)
|
||||
val buttonsListRegister = getInstruction<OneRegisterInstruction>(returnIndex).registerA
|
||||
val freeRegister = findFreeRegister(returnIndex)
|
||||
val freeRegister2 = findFreeRegister(returnIndex, freeRegister)
|
||||
|
||||
fun instructionsRemoveButtonByName(buttonEnumName: String): String {
|
||||
return """
|
||||
fun instructionsRemoveButtonByName(buttonEnumName: String): String = """
|
||||
const-string v$freeRegister, "$buttonEnumName"
|
||||
const-string v$freeRegister2, "$enumNameField"
|
||||
invoke-static { v$buttonsListRegister, v$freeRegister, v$freeRegister2 }, $EXTENSION_CLASS_DESCRIPTOR->removeNavigationButtonByName(Ljava/util/List;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
|
||||
move-result-object v$buttonsListRegister
|
||||
"""
|
||||
}
|
||||
|
||||
if (hideHome!!) {
|
||||
addInstructionsAtControlFlowLabel(
|
||||
returnIndex,
|
||||
instructionsRemoveButtonByName("fragment_feed")
|
||||
instructionsRemoveButtonByName("fragment_feed"),
|
||||
)
|
||||
}
|
||||
|
||||
if (hideReels!!) {
|
||||
addInstructionsAtControlFlowLabel(
|
||||
returnIndex,
|
||||
instructionsRemoveButtonByName("fragment_clips")
|
||||
instructionsRemoveButtonByName("fragment_clips"),
|
||||
)
|
||||
}
|
||||
|
||||
if (hideDirect!!) {
|
||||
addInstructionsAtControlFlowLabel(
|
||||
returnIndex,
|
||||
instructionsRemoveButtonByName("fragment_direct_tab")
|
||||
instructionsRemoveButtonByName("fragment_direct_tab"),
|
||||
)
|
||||
}
|
||||
if (hideSearch!!) {
|
||||
addInstructionsAtControlFlowLabel(
|
||||
returnIndex,
|
||||
instructionsRemoveButtonByName("fragment_search")
|
||||
instructionsRemoveButtonByName("fragment_search"),
|
||||
)
|
||||
}
|
||||
|
||||
if (hideCreate!!) {
|
||||
addInstructionsAtControlFlowLabel(
|
||||
returnIndex,
|
||||
instructionsRemoveButtonByName("fragment_share")
|
||||
instructionsRemoveButtonByName("fragment_share"),
|
||||
)
|
||||
}
|
||||
|
||||
if (hideProfile!!) {
|
||||
addInstructionsAtControlFlowLabel(
|
||||
returnIndex,
|
||||
instructionsRemoveButtonByName("fragment_profile")
|
||||
instructionsRemoveButtonByName("fragment_profile"),
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,6 @@ val `Hide Stories from Home` by creatingBytecodePatch(
|
|||
val addStoryEndIndex = getOrCreateAvatarViewMethod.indices.last()
|
||||
|
||||
// Remove addView of Story.
|
||||
getOrCreateAvatarViewMethod.method.removeInstruction(addStoryEndIndex)
|
||||
getOrCreateAvatarViewMethod.removeInstruction(addStoryEndIndex)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,22 +15,21 @@ val `Enable developer menu` by creatingBytecodePatch(
|
|||
|
||||
It is recommended to use this patch with an alpha/beta Instagram release. Patching a stable release works, but the developer menu shows the developer flags as numbers and does not show a human readable description.
|
||||
""".trimIndentMultiline(),
|
||||
use = false
|
||||
use = false,
|
||||
) {
|
||||
compatibleWith("com.instagram.android")
|
||||
|
||||
apply {
|
||||
with(clearNotificationReceiverFingerprint.method) {
|
||||
indexOfFirstInstructionReversedOrThrow(clearNotificationReceiverFingerprint.stringMatches.first().index) {
|
||||
with(clearNotificationReceiverMethod) {
|
||||
indexOfFirstInstructionReversedOrThrow(clearNotificationReceiverMethod.stringMatches.first().index) {
|
||||
val reference = getReference<MethodReference>()
|
||||
opcode in listOf(Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC_RANGE) &&
|
||||
reference?.parameterTypes?.size == 1 &&
|
||||
reference.parameterTypes.first() == "Lcom/instagram/common/session/UserSession;" &&
|
||||
reference.returnType == "Z"
|
||||
reference?.parameterTypes?.size == 1 &&
|
||||
reference.parameterTypes.first() == "Lcom/instagram/common/session/UserSession;" &&
|
||||
reference.returnType == "Z"
|
||||
}.let { index ->
|
||||
navigate(this).to(index).stop().returnEarly(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
|
||||
package app.revanced.patches.instagram.misc.devmenu
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal val clearNotificationReceiverFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.clearNotificationReceiverMethod by gettingFirstMethodDeclaratively {
|
||||
custom { method, classDef ->
|
||||
method.name == "onReceive" &&
|
||||
classDef.type == "Lcom/instagram/notifications/push/ClearNotificationReceiver;"
|
||||
|
|
|
|||
|
|
@ -2,25 +2,25 @@ package app.revanced.patches.instagram.misc.share
|
|||
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.mutable.MutableMethod
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.mutable.MutableMethod
|
||||
|
||||
context(BytecodePatchContext)
|
||||
internal fun editShareLinksPatch(block: MutableMethod.(index: Int, register: Int) -> Unit) {
|
||||
val fingerprintsToPatch = arrayOf(
|
||||
permalinkResponseJsonParserFingerprint,
|
||||
storyUrlResponseJsonParserFingerprint,
|
||||
profileUrlResponseJsonParserFingerprint,
|
||||
liveUrlResponseJsonParserFingerprint
|
||||
permalinkResponseJsonParserMethod,
|
||||
storyUrlResponseJsonParserMethod,
|
||||
profileUrlResponseJsonParserMethod,
|
||||
liveUrlResponseJsonParserMethod,
|
||||
)
|
||||
|
||||
for (fingerprint in fingerprintsToPatch) {
|
||||
fingerprint.method.apply {
|
||||
val putSharingUrlIndex = indexOfFirstInstruction(
|
||||
permalinkResponseJsonParserFingerprint.stringMatches.first().index,
|
||||
Opcode.IPUT_OBJECT
|
||||
permalinkResponseJsonParserMethod.stringMatches.first().index,
|
||||
Opcode.IPUT_OBJECT,
|
||||
)
|
||||
|
||||
val sharingUrlRegister = getInstruction<TwoRegisterInstruction>(putSharingUrlIndex).registerA
|
||||
|
|
|
|||
|
|
@ -1,24 +1,23 @@
|
|||
package app.revanced.patches.instagram.misc.share
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import com.google.common.util.concurrent.Striped.custom
|
||||
|
||||
internal val permalinkResponseJsonParserFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.permalinkResponseJsonParserMethod by gettingFirstMethodDeclaratively {
|
||||
strings("permalink", "PermalinkResponse")
|
||||
custom { method, _ -> method.name == "parseFromJson" }
|
||||
}
|
||||
|
||||
internal val storyUrlResponseJsonParserFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.storyUrlResponseJsonParserMethod by gettingFirstMethodDeclaratively {
|
||||
strings("story_item_to_share_url", "StoryItemUrlResponse")
|
||||
custom { method, _ -> method.name == "parseFromJson" }
|
||||
}
|
||||
|
||||
internal val profileUrlResponseJsonParserFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.profileUrlResponseJsonParserMethod by gettingFirstMethodDeclaratively {
|
||||
strings("profile_to_share_url", "ProfileUrlResponse")
|
||||
custom { method, _ -> method.name == "parseFromJson" }
|
||||
}
|
||||
|
||||
internal val liveUrlResponseJsonParserFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.liveUrlResponseJsonParserMethod by gettingFirstMethodDeclaratively {
|
||||
strings("live_to_share_url", "LiveItemLinkUrlResponse")
|
||||
custom { method, _ -> method.name == "parseFromJson" }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ internal const val EXTENSION_CLASS_DESCRIPTOR =
|
|||
@Suppress("unused")
|
||||
val `Change link sharing domain` by creatingBytecodePatch(
|
||||
description = "Replaces the domain name of shared links.",
|
||||
use = false
|
||||
use = false,
|
||||
) {
|
||||
compatibleWith("com.instagram.android")
|
||||
|
||||
|
|
@ -22,11 +22,11 @@ val `Change link sharing domain` by creatingBytecodePatch(
|
|||
val customDomainHost by stringOption(
|
||||
default = "imginn.com",
|
||||
name = "Domain name",
|
||||
description = "The domain name to use when sharing links."
|
||||
description = "The domain name to use when sharing links.",
|
||||
)
|
||||
|
||||
apply {
|
||||
getCustomShareDomainFingerprint.method.returnEarly(customDomainHost!!)
|
||||
getCustomShareDomainMethod.returnEarly(customDomainHost!!)
|
||||
|
||||
editShareLinksPatch { index, register ->
|
||||
addInstructions(
|
||||
|
|
@ -34,7 +34,7 @@ val `Change link sharing domain` by creatingBytecodePatch(
|
|||
"""
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->setCustomShareDomain(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$register
|
||||
"""
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
package app.revanced.patches.instagram.misc.share.domain
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val getCustomShareDomainFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.getCustomShareDomainMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||
returnType("Ljava/lang/String;")
|
||||
parameterTypes()
|
||||
|
|
|
|||
|
|
@ -1,15 +1,22 @@
|
|||
package app.revanced.patches.instagram.misc.signature
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal val isValidSignatureClassFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.isValidSignatureClassMethod by gettingFirstMethodDeclaratively {
|
||||
strings("The provider for uri '", "' is not trusted: ")
|
||||
}
|
||||
|
||||
internal val isValidSignatureMethodFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.isValidSignatureMethodMethod by gettingFirstMethodDeclaratively {
|
||||
parameterTypes("L", "Z")
|
||||
returnType("Z")
|
||||
custom { method, _ ->
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@ import app.revanced.util.returnEarly
|
|||
@Suppress("unused")
|
||||
val `Disable signature check` by creatingBytecodePatch(
|
||||
description = "Disables the signature check that can cause the app to crash on startup. " +
|
||||
"Using this patch may cause issues with sharing or opening external Instagram links.",
|
||||
use = false
|
||||
"Using this patch may cause issues with sharing or opening external Instagram links.",
|
||||
use = false,
|
||||
) {
|
||||
compatibleWith("com.instagram.android")
|
||||
|
||||
apply {
|
||||
isValidSignatureMethodFingerprint
|
||||
.match(isValidSignatureClassFingerprint.classDef)
|
||||
isValidSignatureMethodMethod
|
||||
.match(isValidSignatureClassMethod.classDef)
|
||||
.method
|
||||
.returnEarly(true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,16 @@
|
|||
package app.revanced.patches.music.ad.video
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val showVideoAdsParentFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.showVideoAdsParentMethod by gettingFirstMethodDeclaratively {
|
||||
opcodes(
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ val `Hide music video ads` by creatingBytecodePatch(
|
|||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.29.52",
|
||||
"8.10.52"
|
||||
)
|
||||
"8.10.52",
|
||||
),
|
||||
)
|
||||
|
||||
apply {
|
||||
|
|
@ -35,15 +35,15 @@ val `Hide music video ads` by creatingBytecodePatch(
|
|||
SwitchPreference("revanced_music_hide_video_ads"),
|
||||
)
|
||||
|
||||
navigate(showVideoAdsParentFingerprint.originalMethod)
|
||||
.to(showVideoAdsParentFingerprint.instructionMatches.first().index + 1)
|
||||
navigate(showVideoAdsParentMethod.originalMethod)
|
||||
.to(showVideoAdsParentMethod.instructionMatches.first().index + 1)
|
||||
.stop()
|
||||
.addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->showVideoAds(Z)Z
|
||||
move-result p1
|
||||
"""
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@ val `Enable exclusive audio playback` by creatingBytecodePatch(
|
|||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.29.52",
|
||||
"8.10.52"
|
||||
)
|
||||
"8.10.52",
|
||||
),
|
||||
)
|
||||
|
||||
apply {
|
||||
allowExclusiveAudioPlaybackFingerprint.method.returnEarly(true)
|
||||
allowExclusiveAudioPlaybackMethod.returnEarly(true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,17 @@
|
|||
package app.revanced.patches.music.audio.exclusiveaudio
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val allowExclusiveAudioPlaybackFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.allowExclusiveAudioPlaybackMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returnType("Z")
|
||||
parameterTypes()
|
||||
|
|
|
|||
|
|
@ -1,10 +1,17 @@
|
|||
package app.revanced.patches.music.layout.compactheader
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val chipCloudFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.chipCloudMethod by gettingFirstMethodDeclaratively {
|
||||
returnType("V")
|
||||
opcodes(
|
||||
Opcode.CONST,
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ val `Hide category bar` by creatingBytecodePatch(
|
|||
|
||||
chipCloud = ResourceType.LAYOUT["chip_cloud"]
|
||||
|
||||
chipCloudFingerprint.method.apply {
|
||||
val targetIndex = chipCloudFingerprint.patternMatch.endIndex
|
||||
chipCloudMethod.apply {
|
||||
val targetIndex = chipCloudMethod.patternMatch.endIndex
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
|
|
|
|||
|
|
@ -22,20 +22,20 @@ private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/music/pa
|
|||
|
||||
@Suppress("unused")
|
||||
val `Change miniplayer color` by creatingBytecodePatch(
|
||||
description = "Adds an option to change the miniplayer background color to match the fullscreen player."
|
||||
description = "Adds an option to change the miniplayer background color to match the fullscreen player.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
resourceMappingPatch
|
||||
resourceMappingPatch,
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.29.52",
|
||||
"8.10.52"
|
||||
)
|
||||
"8.10.52",
|
||||
),
|
||||
)
|
||||
|
||||
apply {
|
||||
|
|
@ -45,34 +45,37 @@ val `Change miniplayer color` by creatingBytecodePatch(
|
|||
SwitchPreference("revanced_music_change_miniplayer_color"),
|
||||
)
|
||||
|
||||
switchToggleColorFingerprint.match(miniPlayerConstructorFingerprint.classDef).let {
|
||||
switchToggleColorMethod.match(miniPlayerConstructorMethod.classDef).let {
|
||||
val relativeIndex = it.patternMatch.endIndex + 1
|
||||
|
||||
val invokeVirtualIndex = it.method.indexOfFirstInstructionOrThrow(
|
||||
relativeIndex, Opcode.INVOKE_VIRTUAL
|
||||
relativeIndex,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
)
|
||||
val colorMathPlayerInvokeVirtualReference = it.method
|
||||
.getInstruction<ReferenceInstruction>(invokeVirtualIndex).reference
|
||||
|
||||
val iGetIndex = it.method.indexOfFirstInstructionOrThrow(
|
||||
relativeIndex, Opcode.IGET
|
||||
relativeIndex,
|
||||
Opcode.IGET,
|
||||
)
|
||||
val colorMathPlayerIGetReference = it.method
|
||||
.getInstruction<ReferenceInstruction>(iGetIndex).reference as FieldReference
|
||||
|
||||
val colorGreyIndex = miniPlayerConstructorFingerprint.method.indexOfFirstInstructionReversedOrThrow {
|
||||
val colorGreyIndex = miniPlayerConstructorMethod.indexOfFirstInstructionReversedOrThrow {
|
||||
getReference<MethodReference>()?.name == "getColor"
|
||||
}
|
||||
val iPutIndex = miniPlayerConstructorFingerprint.method.indexOfFirstInstructionOrThrow(
|
||||
colorGreyIndex, Opcode.IPUT
|
||||
val iPutIndex = miniPlayerConstructorMethod.indexOfFirstInstructionOrThrow(
|
||||
colorGreyIndex,
|
||||
Opcode.IPUT,
|
||||
)
|
||||
val colorMathPlayerIPutReference = miniPlayerConstructorFingerprint.method
|
||||
val colorMathPlayerIPutReference = miniPlayerConstructorMethod
|
||||
.getInstruction<ReferenceInstruction>(iPutIndex).reference
|
||||
|
||||
miniPlayerConstructorFingerprint.classDef.methods.single { method ->
|
||||
miniPlayerConstructorMethod.classDef.methods.single { method ->
|
||||
method.accessFlags == AccessFlags.PUBLIC.value or AccessFlags.FINAL.value &&
|
||||
method.returnType == "V" &&
|
||||
method.parameters == it.originalMethod.parameters
|
||||
method.returnType == "V" &&
|
||||
method.parameters == it.originalMethod.parameters
|
||||
}.apply {
|
||||
val insertIndex = indexOfFirstInstructionReversedOrThrow(Opcode.INVOKE_DIRECT)
|
||||
val freeRegister = findFreeRegister(insertIndex)
|
||||
|
|
@ -90,7 +93,7 @@ val `Change miniplayer color` by creatingBytecodePatch(
|
|||
iput v$freeRegister, p0, $colorMathPlayerIPutReference
|
||||
:off
|
||||
nop
|
||||
"""
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,18 @@
|
|||
package app.revanced.patches.music.layout.miniplayercolor
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import app.revanced.patches.shared.misc.mapping.ResourceType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val miniPlayerConstructorFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.miniPlayerConstructorMethod by gettingFirstMethodDeclaratively {
|
||||
returnType("V")
|
||||
instructions(
|
||||
ResourceType.ID("mpp_player_bottom_sheet"),
|
||||
|
|
@ -14,9 +21,9 @@ internal val miniPlayerConstructorFingerprint = fingerprint {
|
|||
}
|
||||
|
||||
/**
|
||||
* Matches to the class found in [miniPlayerConstructorFingerprint].
|
||||
* Matches to the class found in [miniPlayerConstructorMethod].
|
||||
*/
|
||||
internal val switchToggleColorFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.switchToggleColorMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL)
|
||||
returnType("V")
|
||||
parameterTypes("L", "J")
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
package app.revanced.patches.music.layout.navigationbar
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import app.revanced.util.containsLiteralInstruction
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
|
|
@ -9,7 +16,7 @@ import com.android.tools.smali.dexlib2.Opcode
|
|||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal val tabLayoutTextFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.tabLayoutTextMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returnType("V")
|
||||
parameterTypes("L")
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ val `Navigation bar` by creatingBytecodePatch(
|
|||
),
|
||||
)
|
||||
|
||||
tabLayoutTextFingerprint.method.apply {
|
||||
tabLayoutTextMethod.apply {
|
||||
// Hide navigation labels.
|
||||
val constIndex = indexOfFirstLiteralInstructionOrThrow(text1)
|
||||
val targetIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.CHECK_CAST)
|
||||
|
|
@ -99,7 +99,7 @@ val `Navigation bar` by creatingBytecodePatch(
|
|||
)
|
||||
|
||||
// Set navigation enum and hide navigation buttons.
|
||||
val enumIndex = tabLayoutTextFingerprint.patternMatch.startIndex + 3
|
||||
val enumIndex = tabLayoutTextMethod.patternMatch.startIndex + 3
|
||||
val enumRegister = getInstruction<OneRegisterInstruction>(enumIndex).registerA
|
||||
val insertEnumIndex = indexOfFirstInstructionOrThrow(Opcode.AND_INT_LIT8) - 2
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
package app.revanced.patches.nunl.ads
|
||||
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnTypeinternal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val BytecodePatchContext.jwPlayerConfigMethod by gettingFirstMutableMethodDeclaratively {
|
||||
import com.android.tools.smali.dexlib2.Opcode val BytecodePatchContext.jwPlayerConfigMethod by gettingFirstMutableMethodDeclaratively {
|
||||
name("advertisingConfig")
|
||||
definingClass($$"Lcom/jwplayer/pub/api/configuration/PlayerConfig$Builder;")
|
||||
accessFlags(AccessFlags.PUBLIC)
|
||||
|
|
|
|||
|
|
@ -27,13 +27,13 @@ private val mipmapDirectories = mapOf(
|
|||
"mipmap-hdpi" to "162x162 px",
|
||||
"mipmap-xhdpi" to "216x216 px",
|
||||
"mipmap-xxhdpi" to "324x324 px",
|
||||
"mipmap-xxxhdpi" to "432x432 px"
|
||||
"mipmap-xxxhdpi" to "432x432 px",
|
||||
)
|
||||
|
||||
private val iconStyleNames = arrayOf(
|
||||
"rounded",
|
||||
"minimal",
|
||||
"scaled"
|
||||
"scaled",
|
||||
)
|
||||
|
||||
private const val ORIGINAL_USER_ICON_STYLE_NAME = "original"
|
||||
|
|
@ -47,7 +47,7 @@ private const val NOTIFICATION_ICON_NAME = "revanced_notification_icon"
|
|||
|
||||
private val USER_CUSTOM_ADAPTIVE_FILE_NAMES = arrayOf(
|
||||
"$LAUNCHER_ADAPTIVE_BACKGROUND_PREFIX$CUSTOM_USER_ICON_STYLE_NAME.png",
|
||||
"$LAUNCHER_ADAPTIVE_FOREGROUND_PREFIX$CUSTOM_USER_ICON_STYLE_NAME.png"
|
||||
"$LAUNCHER_ADAPTIVE_FOREGROUND_PREFIX$CUSTOM_USER_ICON_STYLE_NAME.png",
|
||||
)
|
||||
|
||||
private const val USER_CUSTOM_MONOCHROME_FILE_NAME =
|
||||
|
|
@ -71,15 +71,15 @@ internal fun baseCustomBrandingPatch(
|
|||
activityAliasNameWithIntents: String,
|
||||
preferenceScreen: BasePreferenceScreen.Screen,
|
||||
block: ResourcePatchBuilder.() -> Unit,
|
||||
executeBlock: ResourcePatchContext.() -> Unit = {}
|
||||
executeBlock: ResourcePatchContext.() -> Unit = {},
|
||||
) = resourcePatch(
|
||||
name = "Custom branding",
|
||||
description = "Adds options to change the app icon and app name. " +
|
||||
"Branding cannot be changed for mounted (root) installations."
|
||||
"Branding cannot be changed for mounted (root) installations.",
|
||||
) {
|
||||
val customName by stringOption(
|
||||
name = "App name",
|
||||
description = "Custom app name."
|
||||
description = "Custom app name.",
|
||||
)
|
||||
|
||||
val customIcon by stringOption(
|
||||
|
|
@ -99,7 +99,7 @@ internal fun baseCustomBrandingPatch(
|
|||
Optionally, the path contains a 'drawable' folder with any of the monochrome icon files:
|
||||
$USER_CUSTOM_MONOCHROME_FILE_NAME
|
||||
$USER_CUSTOM_NOTIFICATION_ICON_FILE_NAME
|
||||
""".trimIndentMultiline()
|
||||
""".trimIndentMultiline(),
|
||||
)
|
||||
|
||||
block()
|
||||
|
|
@ -112,12 +112,12 @@ internal fun baseCustomBrandingPatch(
|
|||
apply {
|
||||
getMainActivityOnCreate().addInstruction(
|
||||
0,
|
||||
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->setBranding()V"
|
||||
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->setBranding()V",
|
||||
)
|
||||
|
||||
numberOfPresetAppNamesExtensionFingerprint.method.returnEarly(numberOfPresetAppNames)
|
||||
numberOfPresetAppNamesExtensionMethod.returnEarly(numberOfPresetAppNames)
|
||||
|
||||
notificationFingerprint.method.apply {
|
||||
notificationMethod.apply {
|
||||
val getBuilderIndex = if (isYouTubeMusic) {
|
||||
// YT Music the field is not a plain object type.
|
||||
indexOfFirstInstructionOrThrow {
|
||||
|
|
@ -128,7 +128,7 @@ internal fun baseCustomBrandingPatch(
|
|||
val builderCastIndex = indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<TypeReference>()
|
||||
opcode == Opcode.CHECK_CAST &&
|
||||
reference?.type == "Landroid/app/Notification\$Builder;"
|
||||
reference?.type == "Landroid/app/Notification\$Builder;"
|
||||
}
|
||||
indexOfFirstInstructionReversedOrThrow(builderCastIndex) {
|
||||
getReference<FieldReference>()?.type == "Ljava/lang/Object;"
|
||||
|
|
@ -139,7 +139,7 @@ internal fun baseCustomBrandingPatch(
|
|||
.getReference<FieldReference>()
|
||||
|
||||
findInstructionIndicesReversedOrThrow(
|
||||
Opcode.RETURN_VOID
|
||||
Opcode.RETURN_VOID,
|
||||
).forEach { index ->
|
||||
addInstructionsAtControlFlowLabel(
|
||||
index,
|
||||
|
|
@ -148,7 +148,7 @@ internal fun baseCustomBrandingPatch(
|
|||
iget-object v0, v0, $builderFieldName
|
||||
check-cast v0, Landroid/app/Notification${'$'}Builder;
|
||||
invoke-static { v0 }, $EXTENSION_CLASS_DESCRIPTOR->setNotificationIcon(Landroid/app/Notification${'$'}Builder;)V
|
||||
"""
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -166,7 +166,7 @@ internal fun baseCustomBrandingPatch(
|
|||
if (customName != null || customIcon != null) {
|
||||
if (setOrGetFallbackPackageName(originalAppPackageName) == originalAppPackageName) {
|
||||
Logger.getLogger(this::class.java.name).warning(
|
||||
"Custom branding does not work with root installation. No changes applied."
|
||||
"Custom branding does not work with root installation. No changes applied.",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -181,7 +181,7 @@ internal fun baseCustomBrandingPatch(
|
|||
ListPreference(
|
||||
key = "revanced_custom_branding_name",
|
||||
entriesKey = "revanced_custom_branding_name_custom_entries",
|
||||
entryValuesKey = "revanced_custom_branding_name_custom_entry_values"
|
||||
entryValuesKey = "revanced_custom_branding_name_custom_entry_values",
|
||||
)
|
||||
} else {
|
||||
ListPreference("revanced_custom_branding_name")
|
||||
|
|
@ -190,11 +190,11 @@ internal fun baseCustomBrandingPatch(
|
|||
ListPreference(
|
||||
key = "revanced_custom_branding_icon",
|
||||
entriesKey = "revanced_custom_branding_icon_custom_entries",
|
||||
entryValuesKey = "revanced_custom_branding_icon_custom_entry_values"
|
||||
entryValuesKey = "revanced_custom_branding_icon_custom_entry_values",
|
||||
)
|
||||
} else {
|
||||
ListPreference("revanced_custom_branding_icon")
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
val useCustomName = customName != null
|
||||
|
|
@ -211,8 +211,8 @@ internal fun baseCustomBrandingPatch(
|
|||
),
|
||||
ResourceGroup(
|
||||
"mipmap-anydpi",
|
||||
"$LAUNCHER_RESOURCE_NAME_PREFIX$style.xml"
|
||||
)
|
||||
"$LAUNCHER_RESOURCE_NAME_PREFIX$style.xml",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -221,19 +221,19 @@ internal fun baseCustomBrandingPatch(
|
|||
// Push notification 'small' icon.
|
||||
ResourceGroup(
|
||||
"drawable",
|
||||
"$NOTIFICATION_ICON_NAME.xml"
|
||||
"$NOTIFICATION_ICON_NAME.xml",
|
||||
),
|
||||
|
||||
// Copy template user icon, because the aliases must be added even if no user icon is provided.
|
||||
ResourceGroup(
|
||||
"drawable",
|
||||
USER_CUSTOM_MONOCHROME_FILE_NAME,
|
||||
USER_CUSTOM_NOTIFICATION_ICON_FILE_NAME
|
||||
USER_CUSTOM_NOTIFICATION_ICON_FILE_NAME,
|
||||
),
|
||||
ResourceGroup(
|
||||
"mipmap-anydpi",
|
||||
"$LAUNCHER_RESOURCE_NAME_PREFIX$CUSTOM_USER_ICON_STYLE_NAME.xml"
|
||||
)
|
||||
"$LAUNCHER_RESOURCE_NAME_PREFIX$CUSTOM_USER_ICON_STYLE_NAME.xml",
|
||||
),
|
||||
)
|
||||
|
||||
// Copy template icon files.
|
||||
|
|
@ -244,7 +244,7 @@ internal fun baseCustomBrandingPatch(
|
|||
dpi,
|
||||
"$LAUNCHER_ADAPTIVE_BACKGROUND_PREFIX$CUSTOM_USER_ICON_STYLE_NAME.png",
|
||||
"$LAUNCHER_ADAPTIVE_FOREGROUND_PREFIX$CUSTOM_USER_ICON_STYLE_NAME.png",
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -256,7 +256,7 @@ internal fun baseCustomBrandingPatch(
|
|||
appNameIndex: Int,
|
||||
useCustomName: Boolean,
|
||||
enabled: Boolean,
|
||||
intents: NodeList
|
||||
intents: NodeList,
|
||||
): Element {
|
||||
val label = if (useCustomName) {
|
||||
if (customName == null) {
|
||||
|
|
@ -293,7 +293,7 @@ internal fun baseCustomBrandingPatch(
|
|||
} else {
|
||||
for (i in 0 until intents.length) {
|
||||
alias.appendChild(
|
||||
intents.item(i).cloneNode(true)
|
||||
intents.item(i).cloneNode(true),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -304,7 +304,7 @@ internal fun baseCustomBrandingPatch(
|
|||
val application = document.getElementsByTagName("application").item(0) as Element
|
||||
val intentFilters = document.childNodes.findElementByAttributeValueOrThrow(
|
||||
"android:name",
|
||||
activityAliasNameWithIntents
|
||||
activityAliasNameWithIntents,
|
||||
).childNodes
|
||||
|
||||
// The YT application name can appear in some places along side the system
|
||||
|
|
@ -313,7 +313,7 @@ internal fun baseCustomBrandingPatch(
|
|||
// use a custom name for this situation to disambiguate which app is which.
|
||||
application.setAttribute(
|
||||
"android:label",
|
||||
"@string/revanced_custom_branding_name_entry_2"
|
||||
"@string/revanced_custom_branding_name_entry_2",
|
||||
)
|
||||
|
||||
for (appNameIndex in 1..numberOfPresetAppNames) {
|
||||
|
|
@ -329,8 +329,8 @@ internal fun baseCustomBrandingPatch(
|
|||
appNameIndex = appNameIndex,
|
||||
useCustomName = useCustomNameLabel,
|
||||
enabled = (appNameIndex == 1),
|
||||
intentFilters
|
||||
)
|
||||
intentFilters,
|
||||
),
|
||||
)
|
||||
|
||||
// Bundled icons.
|
||||
|
|
@ -342,8 +342,8 @@ internal fun baseCustomBrandingPatch(
|
|||
appNameIndex = appNameIndex,
|
||||
useCustomName = useCustomNameLabel,
|
||||
enabled = false,
|
||||
intentFilters
|
||||
)
|
||||
intentFilters,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -362,8 +362,8 @@ internal fun baseCustomBrandingPatch(
|
|||
appNameIndex = appNameIndex,
|
||||
useCustomName = useCustomNameLabel,
|
||||
enabled = false,
|
||||
intentFilters
|
||||
)
|
||||
intentFilters,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -371,7 +371,7 @@ internal fun baseCustomBrandingPatch(
|
|||
// can be shown in the launcher. Can only be done after adding the new aliases.
|
||||
intentFilters.findElementByAttributeValueOrThrow(
|
||||
"android:name",
|
||||
"android.intent.action.MAIN"
|
||||
"android.intent.action.MAIN",
|
||||
).removeFromParent()
|
||||
}
|
||||
|
||||
|
|
@ -383,13 +383,13 @@ internal fun baseCustomBrandingPatch(
|
|||
|
||||
if (!iconPathFile.exists()) {
|
||||
throw PatchException(
|
||||
"The custom icon path cannot be found: " + iconPathFile.absolutePath
|
||||
"The custom icon path cannot be found: " + iconPathFile.absolutePath,
|
||||
)
|
||||
}
|
||||
|
||||
if (!iconPathFile.isDirectory) {
|
||||
throw PatchException(
|
||||
"The custom icon path must be a folder: " + iconPathFile.absolutePath
|
||||
"The custom icon path must be a folder: " + iconPathFile.absolutePath,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -413,7 +413,8 @@ internal fun baseCustomBrandingPatch(
|
|||
if (customFiles.isNotEmpty() && customFiles.size != USER_CUSTOM_ADAPTIVE_FILE_NAMES.size) {
|
||||
throw PatchException(
|
||||
"Must include all required icon files " +
|
||||
"but only found " + customFiles.map { it.name })
|
||||
"but only found " + customFiles.map { it.name },
|
||||
)
|
||||
}
|
||||
|
||||
customFiles.forEach { imgSourceFile ->
|
||||
|
|
@ -427,14 +428,14 @@ internal fun baseCustomBrandingPatch(
|
|||
// Copy monochrome and small notification icon if it provided.
|
||||
arrayOf(
|
||||
USER_CUSTOM_MONOCHROME_FILE_NAME,
|
||||
USER_CUSTOM_NOTIFICATION_ICON_FILE_NAME
|
||||
USER_CUSTOM_NOTIFICATION_ICON_FILE_NAME,
|
||||
).forEach { fileName ->
|
||||
val relativePath = "drawable/$fileName"
|
||||
val file = iconPathFile.resolve(relativePath)
|
||||
if (file.exists()) {
|
||||
file.copyTo(
|
||||
target = resourceDirectory.resolve(relativePath),
|
||||
overwrite = true
|
||||
overwrite = true,
|
||||
)
|
||||
copiedFiles = true
|
||||
}
|
||||
|
|
@ -442,9 +443,9 @@ internal fun baseCustomBrandingPatch(
|
|||
|
||||
if (!copiedFiles) {
|
||||
throw PatchException(
|
||||
"Expected to find directories and files: "
|
||||
+ USER_CUSTOM_ADAPTIVE_FILE_NAMES.contentToString()
|
||||
+ "\nBut none were found in the provided option file path: " + iconPathFile.absolutePath
|
||||
"Expected to find directories and files: " +
|
||||
USER_CUSTOM_ADAPTIVE_FILE_NAMES.contentToString() +
|
||||
"\nBut none were found in the provided option file path: " + iconPathFile.absolutePath,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,16 @@
|
|||
package app.revanced.patches.shared.layout.branding
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val numberOfPresetAppNamesExtensionFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.numberOfPresetAppNamesExtensionMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||
returnType("I")
|
||||
parameterTypes()
|
||||
|
|
@ -14,7 +21,7 @@ internal val numberOfPresetAppNamesExtensionFingerprint = fingerprint {
|
|||
|
||||
// A much simpler fingerprint exists that can set the small icon (contains string "414843287017"),
|
||||
// but that has limited usage and this fingerprint allows changing any part of the notification.
|
||||
internal val notificationFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.notificationMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
parameterTypes("L")
|
||||
strings("key_action_priority")
|
||||
|
|
|
|||
|
|
@ -2,13 +2,20 @@ package app.revanced.patches.shared.layout.theme
|
|||
|
||||
import app.revanced.patcher.InstructionLocation.MatchAfterImmediately
|
||||
import app.revanced.patcher.InstructionLocation.MatchAfterWithin
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.fieldAccess
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.methodCall
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val lithoOnBoundsChangeFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.lithoOnBoundsChangeMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PROTECTED, AccessFlags.FINAL)
|
||||
returnType("V")
|
||||
parameterTypes("Landroid/graphics/Rect;")
|
||||
|
|
|
|||
|
|
@ -11,15 +11,15 @@ val lithoColorHookPatch = bytecodePatch(
|
|||
) {
|
||||
|
||||
apply {
|
||||
var insertionIndex = lithoOnBoundsChangeFingerprint.patternMatch.endIndex - 1
|
||||
var insertionIndex = lithoOnBoundsChangeMethod.patternMatch.endIndex - 1
|
||||
|
||||
lithoColorOverrideHook = { targetMethodClass, targetMethodName ->
|
||||
lithoOnBoundsChangeFingerprint.method.addInstructions(
|
||||
lithoOnBoundsChangeMethod.addInstructions(
|
||||
insertionIndex,
|
||||
"""
|
||||
invoke-static { p1 }, $targetMethodClass->$targetMethodName(I)I
|
||||
move-result p1
|
||||
"""
|
||||
""",
|
||||
)
|
||||
insertionIndex += 2
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,17 @@
|
|||
package app.revanced.patches.shared.misc.fix.verticalscroll
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val canScrollVerticallyFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.canScrollVerticallyMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returnType("Z")
|
||||
parameterTypes()
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ val verticalScrollPatch = bytecodePatch(
|
|||
) {
|
||||
|
||||
apply {
|
||||
canScrollVerticallyFingerprint.let {
|
||||
canScrollVerticallyMethod.let {
|
||||
it.method.apply {
|
||||
val moveResultIndex = it.instructionMatches.last().index
|
||||
val moveResultRegister = getInstruction<OneRegisterInstruction>(moveResultIndex).registerA
|
||||
|
|
|
|||
|
|
@ -1,9 +1,16 @@
|
|||
package app.revanced.patches.shared.misc.gms
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val googlePlayUtilityFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.googlePlayUtilityMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returnType("I")
|
||||
parameterTypes("L", "I")
|
||||
|
|
@ -14,14 +21,14 @@ internal val googlePlayUtilityFingerprint = fingerprint {
|
|||
)
|
||||
}
|
||||
|
||||
internal val serviceCheckFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.serviceCheckMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returnType("V")
|
||||
parameterTypes("L", "I")
|
||||
strings("Google Play Services not available")
|
||||
}
|
||||
|
||||
internal val gmsCoreSupportFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.gmsCoreSupportMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||
returnType("Ljava/lang/String;")
|
||||
parameterTypes()
|
||||
|
|
@ -30,7 +37,7 @@ internal val gmsCoreSupportFingerprint = fingerprint {
|
|||
}
|
||||
}
|
||||
|
||||
internal val originalPackageNameExtensionFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.originalPackageNameExtensionMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||
returnType("Ljava/lang/String;")
|
||||
parameterTypes()
|
||||
|
|
|
|||
|
|
@ -57,14 +57,14 @@ fun gmsCoreSupportPatch(
|
|||
) = bytecodePatch(
|
||||
name = "GmsCore support", // TODO
|
||||
description = "Allows the app to work without root by using a different package name when patched " +
|
||||
"using a GmsCore instead of Google Play Services.",
|
||||
"using a GmsCore instead of Google Play Services.",
|
||||
) {
|
||||
val gmsCoreVendorGroupIdOption = stringOption(
|
||||
default = "app.revanced",
|
||||
values =
|
||||
mapOf(
|
||||
"ReVanced" to "app.revanced",
|
||||
),
|
||||
mapOf(
|
||||
"ReVanced" to "app.revanced",
|
||||
),
|
||||
name = "GmsCore vendor group ID",
|
||||
description = "The vendor's group ID for GmsCore.",
|
||||
required = true,
|
||||
|
|
@ -124,10 +124,11 @@ fun gmsCoreSupportPatch(
|
|||
in PERMISSIONS,
|
||||
in ACTIONS,
|
||||
in AUTHORITIES,
|
||||
-> referencedString.replace("com.google", gmsCoreVendorGroupId!!)
|
||||
-> referencedString.replace("com.google", gmsCoreVendorGroupId!!)
|
||||
|
||||
// No vendor prefix for whatever reason...
|
||||
"subscribedfeeds" -> "$gmsCoreVendorGroupId.subscribedfeeds"
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
|
|
@ -159,7 +160,7 @@ fun gmsCoreSupportPatch(
|
|||
when (string) {
|
||||
"$fromPackageName.SuggestionProvider",
|
||||
"$fromPackageName.fileprovider",
|
||||
-> string.replace(fromPackageName, toPackageName)
|
||||
-> string.replace(fromPackageName, toPackageName)
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
|
@ -203,25 +204,25 @@ fun gmsCoreSupportPatch(
|
|||
|
||||
// Return these methods early to prevent the app from crashing.
|
||||
getEarlyReturnMethods().forEach { it.returnEarly() }
|
||||
serviceCheckFingerprint.method.returnEarly()
|
||||
serviceCheckMethod.returnEarly()
|
||||
|
||||
// Google Play Utility is not present in all apps, so we need to check if it's present.
|
||||
if (googlePlayUtilityFingerprint.methodOrNull != null) {
|
||||
googlePlayUtilityFingerprint.method.returnEarly(0)
|
||||
if (googlePlayUtilityMethodOrNull != null) {
|
||||
googlePlayUtilityMethod.returnEarly(0)
|
||||
}
|
||||
|
||||
// Set original and patched package names for extension to use.
|
||||
originalPackageNameExtensionFingerprint.method.returnEarly(fromPackageName)
|
||||
originalPackageNameExtensionMethod.returnEarly(fromPackageName)
|
||||
|
||||
// Verify GmsCore is installed and whitelisted for power optimizations and background usage.
|
||||
getMainActivityOnCreateMethod().addInstruction(
|
||||
0,
|
||||
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->" +
|
||||
"checkGmsCore(Landroid/app/Activity;)V"
|
||||
"checkGmsCore(Landroid/app/Activity;)V",
|
||||
)
|
||||
|
||||
// Change the vendor of GmsCore in the extension.
|
||||
gmsCoreSupportFingerprint.method.returnEarly(gmsCoreVendorGroupId!!)
|
||||
gmsCoreSupportMethod.returnEarly(gmsCoreVendorGroupId!!)
|
||||
|
||||
executeBlock()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,19 +8,19 @@ import java.util.logging.Logger
|
|||
@Suppress("unused")
|
||||
val `Disable Pairip license check` by creatingBytecodePatch(
|
||||
description = "Disables Play Integrity API (Pairip) client-side license check.",
|
||||
use = false
|
||||
use = false,
|
||||
) {
|
||||
|
||||
apply {
|
||||
if (processLicenseResponseFingerprint.methodOrNull == null || validateLicenseResponseFingerprint.methodOrNull == null) {
|
||||
if (processLicenseResponseMethodOrNull == null || validateLicenseResponseMethodOrNull == null) {
|
||||
return@apply Logger.getLogger(this::class.java.name)
|
||||
.warning("Could not find Pairip licensing check. No changes applied.")
|
||||
}
|
||||
|
||||
// Set first parameter (responseCode) to 0 (success status).
|
||||
processLicenseResponseFingerprint.method.addInstruction(0, "const/4 p1, 0x0")
|
||||
processLicenseResponseMethod.addInstruction(0, "const/4 p1, 0x0")
|
||||
|
||||
// Short-circuit the license response validation.
|
||||
validateLicenseResponseFingerprint.method.returnEarly()
|
||||
validateLicenseResponseMethod.returnEarly()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,15 @@
|
|||
package app.revanced.patches.shared.misc.pairip.license
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal val processLicenseResponseFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.processLicenseResponseMethod by gettingFirstMethodDeclaratively {
|
||||
custom { method, classDef ->
|
||||
classDef.type == "Lcom/pairip/licensecheck/LicenseClient;" &&
|
||||
method.name == "processResponse"
|
||||
method.name == "processResponse"
|
||||
}
|
||||
}
|
||||
|
||||
internal val validateLicenseResponseFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.validateLicenseResponseMethod by gettingFirstMethodDeclaratively {
|
||||
custom { method, classDef ->
|
||||
classDef.type == "Lcom/pairip/licensecheck/ResponseValidator;" &&
|
||||
method.name == "validateResponse"
|
||||
method.name == "validateResponse"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,17 @@
|
|||
package app.revanced.patches.shared.misc.settings
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import app.revanced.patches.shared.misc.extension.EXTENSION_CLASS_DESCRIPTOR
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val themeLightColorResourceNameFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.themeLightColorResourceNameMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||
returnType("Ljava/lang/String;")
|
||||
parameterTypes()
|
||||
|
|
@ -13,7 +20,7 @@ internal val themeLightColorResourceNameFingerprint = fingerprint {
|
|||
}
|
||||
}
|
||||
|
||||
internal val themeDarkColorResourceNameFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.themeDarkColorResourceNameMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||
returnType("Ljava/lang/String;")
|
||||
parameterTypes()
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ import app.revanced.util.insertFirst
|
|||
import app.revanced.util.returnEarly
|
||||
import org.w3c.dom.Node
|
||||
|
||||
private var lightThemeColor : String? = null
|
||||
private var darkThemeColor : String? = null
|
||||
private var lightThemeColor: String? = null
|
||||
private var darkThemeColor: String? = null
|
||||
|
||||
/**
|
||||
* Sets the default theme colors used in various ReVanced specific settings menus.
|
||||
|
|
@ -33,10 +33,10 @@ fun overrideThemeColors(lightThemeColorString: String?, darkThemeColorString: St
|
|||
private val settingsColorPatch = bytecodePatch {
|
||||
afterDependents {
|
||||
if (lightThemeColor != null) {
|
||||
themeLightColorResourceNameFingerprint.method.returnEarly(lightThemeColor!!)
|
||||
themeLightColorResourceNameMethod.returnEarly(lightThemeColor!!)
|
||||
}
|
||||
if (darkThemeColor != null) {
|
||||
themeDarkColorResourceNameFingerprint.method.returnEarly(darkThemeColor!!)
|
||||
themeDarkColorResourceNameMethod.returnEarly(darkThemeColor!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -48,28 +48,31 @@ private val settingsColorPatch = bytecodePatch {
|
|||
* File names that do not exist are ignored and not processed.
|
||||
* @param preferences A set of preferences to add to the ReVanced fragment.
|
||||
*/
|
||||
fun settingsPatch (
|
||||
fun settingsPatch(
|
||||
rootPreferences: List<Pair<BasePreference, String>>? = null,
|
||||
preferences: Set<BasePreference>,
|
||||
) = resourcePatch {
|
||||
dependsOn(
|
||||
addResourcesPatch,
|
||||
settingsColorPatch,
|
||||
addBrandLicensePatch
|
||||
addBrandLicensePatch,
|
||||
)
|
||||
|
||||
apply {
|
||||
copyResources(
|
||||
"settings",
|
||||
ResourceGroup("xml",
|
||||
ResourceGroup(
|
||||
"xml",
|
||||
"revanced_prefs.xml",
|
||||
"revanced_prefs_icons.xml",
|
||||
"revanced_prefs_icons_bold.xml"
|
||||
"revanced_prefs_icons_bold.xml",
|
||||
),
|
||||
ResourceGroup("menu",
|
||||
"revanced_search_menu.xml"
|
||||
ResourceGroup(
|
||||
"menu",
|
||||
"revanced_search_menu.xml",
|
||||
),
|
||||
ResourceGroup("drawable",
|
||||
ResourceGroup(
|
||||
"drawable",
|
||||
// CustomListPreference resources.
|
||||
"revanced_ic_dialog_alert.xml",
|
||||
// Search resources.
|
||||
|
|
@ -84,7 +87,8 @@ fun settingsPatch (
|
|||
"revanced_settings_toolbar_arrow_left.xml",
|
||||
"revanced_settings_toolbar_arrow_left_bold.xml",
|
||||
),
|
||||
ResourceGroup("layout",
|
||||
ResourceGroup(
|
||||
"layout",
|
||||
"revanced_custom_list_item_checked.xml",
|
||||
// Color picker.
|
||||
"revanced_color_dot_widget.xml",
|
||||
|
|
@ -98,8 +102,8 @@ fun settingsPatch (
|
|||
"revanced_preference_search_result_list.xml",
|
||||
"revanced_preference_search_result_regular.xml",
|
||||
"revanced_preference_search_result_switch.xml",
|
||||
"revanced_settings_with_toolbar.xml"
|
||||
)
|
||||
"revanced_settings_with_toolbar.xml",
|
||||
),
|
||||
)
|
||||
|
||||
addResources("shared", "misc.settings.settingsResourcePatch")
|
||||
|
|
|
|||
|
|
@ -3,13 +3,15 @@ package app.revanced.patches.shared.misc.spoof
|
|||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.custom
|
||||
import app.revanced.patcher.extensions.methodReference
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.firstMethodComposite
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.immutableClassDef
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.method
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
|
@ -80,7 +82,7 @@ internal val buildRequestMethodMatch = firstMethodComposite {
|
|||
}
|
||||
}
|
||||
|
||||
internal val protobufClassParseByteBufferFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.protobufClassParseByteBufferMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PROTECTED, AccessFlags.STATIC)
|
||||
returnType("L")
|
||||
parameterTypes("L", "Ljava/nio/ByteBuffer;")
|
||||
|
|
@ -110,7 +112,7 @@ internal val createStreamingDataMethodMatch = firstMethodComposite {
|
|||
}
|
||||
}
|
||||
|
||||
internal val buildMediaDataSourceFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.buildMediaDataSourceMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
parameterTypes(
|
||||
"Landroid/net/Uri;",
|
||||
|
|
@ -145,7 +147,7 @@ internal val mediaFetchEnumConstructorMethodMatch = firstMethodComposite {
|
|||
)
|
||||
}
|
||||
|
||||
internal val nerdsStatsVideoFormatBuilderFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.nerdsStatsVideoFormatBuilderMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returnType("Ljava/lang/String;")
|
||||
parameterTypes("L")
|
||||
|
|
@ -154,7 +156,7 @@ internal val nerdsStatsVideoFormatBuilderFingerprint = fingerprint {
|
|||
)
|
||||
}
|
||||
|
||||
internal val patchIncludedExtensionMethodFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.patchIncludedExtensionMethodMethod by gettingFirstMethodDeclaratively {
|
||||
returnType("Z")
|
||||
parameterTypes()
|
||||
custom { method, classDef ->
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package app.revanced.patches.shared.misc.spoof
|
||||
|
||||
import app.revanced.patcher.extensions.*
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.patch.BytecodePatchBuilder
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
|
|
@ -55,7 +54,7 @@ internal fun spoofVideoStreamsPatch(
|
|||
|
||||
// region Enable extension helper method used by other patches
|
||||
|
||||
patchIncludedExtensionMethodFingerprint.method.returnEarly(true)
|
||||
patchIncludedExtensionMethodMethod.returnEarly(true)
|
||||
|
||||
// endregion
|
||||
|
||||
|
|
@ -128,7 +127,7 @@ internal fun spoofVideoStreamsPatch(
|
|||
"$resultMethodType->$setStreamDataMethodName($videoDetailsClass)V",
|
||||
)
|
||||
|
||||
val protobufClass = protobufClassParseByteBufferFingerprint.method.definingClass
|
||||
val protobufClass = protobufClassParseByteBufferMethod.definingClass
|
||||
val setStreamingDataIndex = createStreamingDataMethodMatch.indices.first()
|
||||
|
||||
val playerProtoClass = getInstruction(setStreamingDataIndex + 1)
|
||||
|
|
@ -212,7 +211,7 @@ internal fun spoofVideoStreamsPatch(
|
|||
// Requesting streams intended for other platforms with a body tuned for Android could be the cause of 400 errors.
|
||||
// A proper fix may include modifying the request body to match the platforms expected body.
|
||||
|
||||
buildMediaDataSourceFingerprint.method.apply {
|
||||
buildMediaDataSourceMethod.apply {
|
||||
val targetIndex = instructions.lastIndex
|
||||
|
||||
// Instructions are added just before the method returns,
|
||||
|
|
@ -238,7 +237,7 @@ internal fun spoofVideoStreamsPatch(
|
|||
|
||||
// region Append spoof info.
|
||||
|
||||
nerdsStatsVideoFormatBuilderFingerprint.method.apply {
|
||||
nerdsStatsVideoFormatBuilderMethod.apply {
|
||||
findInstructionIndicesReversedOrThrow(Opcode.RETURN_OBJECT).forEach { index ->
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ val `Remove badge tab` by creatingBytecodePatch(
|
|||
val arrayTabs = listOf("Log", "HealthCare")
|
||||
|
||||
apply {
|
||||
createTabsFingerprint.method.apply {
|
||||
createTabsMethod.apply {
|
||||
removeInstructions(0, 2)
|
||||
|
||||
val arrayRegister = 0
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
package app.revanced.patches.songpal.badge
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
|
|
@ -8,7 +15,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
|||
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference
|
||||
|
||||
// Located @ ub.i0.h#p (9.5.0)
|
||||
internal val createTabsFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.createTabsMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PRIVATE)
|
||||
returnType("Ljava/util/List;")
|
||||
custom { method, _ ->
|
||||
|
|
@ -26,7 +33,7 @@ internal val createTabsFingerprint = fingerprint {
|
|||
}
|
||||
|
||||
// Located @ com.sony.songpal.mdr.vim.activity.MdrRemoteBaseActivity.e#run (9.5.0)
|
||||
internal val showNotificationFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.showNotificationMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC)
|
||||
returnType("V")
|
||||
custom { method, _ ->
|
||||
|
|
|
|||
|
|
@ -10,6 +10,6 @@ val `Remove notification badge` by creatingBytecodePatch(
|
|||
compatibleWith("com.sony.songpal.mdr"("10.1.0"))
|
||||
|
||||
apply {
|
||||
showNotificationFingerprint.method.addInstructions(0, "return-void")
|
||||
showNotificationMethod.addInstructions(0, "return-void")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ private val customThemeBytecodePatch = bytecodePatch {
|
|||
dependsOn(sharedExtensionPatch)
|
||||
|
||||
apply {
|
||||
val colorSpaceUtilsClassDef = colorSpaceUtilsClassFingerprint.originalClassDef
|
||||
val colorSpaceUtilsClassDef = colorSpaceUtilsClassMethod.originalClassDef
|
||||
|
||||
// Hook a util method that converts ARGB to RGBA in the sRGB color space to replace hardcoded accent colors.
|
||||
convertArgbToRgbaFingerprint.match(colorSpaceUtilsClassDef).method.apply {
|
||||
convertArgbToRgbaMethod.match(colorSpaceUtilsClassDef).method.apply {
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
|
|
@ -30,21 +30,21 @@ private val customThemeBytecodePatch = bytecodePatch {
|
|||
invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->replaceColor(I)I
|
||||
move-result p0
|
||||
int-to-long p0, p0
|
||||
"""
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
// Lottie JSON parser method. It parses the JSON Lottie animation into its own class,
|
||||
// including the solid color of it.
|
||||
parseLottieJsonFingerprint.method.apply {
|
||||
parseLottieJsonMethod.apply {
|
||||
val invokeParseColorIndex = indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.definingClass == "Landroid/graphics/Color;"
|
||||
&& reference.name == "parseColor"
|
||||
reference?.definingClass == "Landroid/graphics/Color;" &&
|
||||
reference.name == "parseColor"
|
||||
}
|
||||
val parsedColorRegister = getInstruction<OneRegisterInstruction>(invokeParseColorIndex + 1).registerA
|
||||
|
||||
val replaceColorDescriptor = "$EXTENSION_CLASS_DESCRIPTOR->replaceColor(I)I"
|
||||
val replaceColorDescriptor = "$EXTENSION_CLASS_DESCRIPTOR->replaceColor(I)I"
|
||||
|
||||
addInstructions(
|
||||
invokeParseColorIndex + 2,
|
||||
|
|
@ -52,16 +52,16 @@ private val customThemeBytecodePatch = bytecodePatch {
|
|||
# Use invoke-static/range because the register number is too large.
|
||||
invoke-static/range { v$parsedColorRegister .. v$parsedColorRegister }, $replaceColorDescriptor
|
||||
move-result v$parsedColorRegister
|
||||
"""
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
// Lottie animated color parser.
|
||||
parseAnimatedColorFingerprint.method.apply {
|
||||
parseAnimatedColorMethod.apply {
|
||||
val invokeArgbIndex = indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.definingClass == "Landroid/graphics/Color;"
|
||||
&& reference.name == "argb"
|
||||
reference?.definingClass == "Landroid/graphics/Color;" &&
|
||||
reference.name == "argb"
|
||||
}
|
||||
val argbColorRegister = getInstruction<OneRegisterInstruction>(invokeArgbIndex + 1).registerA
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ private val customThemeBytecodePatch = bytecodePatch {
|
|||
"""
|
||||
invoke-static { v$argbColorRegister }, $EXTENSION_CLASS_DESCRIPTOR->replaceColor(I)I
|
||||
move-result v$argbColorRegister
|
||||
"""
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -97,7 +97,7 @@ val customThemePatch = resourcePatch(
|
|||
default = false,
|
||||
name = "Override player gradient color",
|
||||
description =
|
||||
"Apply primary background color to the player gradient color, which changes dynamically with the song.",
|
||||
"Apply primary background color to the player gradient color, which changes dynamically with the song.",
|
||||
required = false,
|
||||
)
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ val customThemePatch = resourcePatch(
|
|||
default = "#FF121212",
|
||||
name = "Secondary background color",
|
||||
description = "The secondary background color. (e.g. playlist list in home, player artist, song credits). " +
|
||||
"Can be a hex color or a resource reference.\",",
|
||||
"Can be a hex color or a resource reference.\",",
|
||||
required = true,
|
||||
)
|
||||
|
||||
|
|
@ -120,7 +120,7 @@ val customThemePatch = resourcePatch(
|
|||
default = "#FF1ABC54",
|
||||
name = "Pressed accent color",
|
||||
description = "The color when accented buttons are pressed, by default slightly darker than accent. " +
|
||||
"Can be a hex color or a resource reference.",
|
||||
"Can be a hex color or a resource reference.",
|
||||
required = true,
|
||||
)
|
||||
|
||||
|
|
@ -155,7 +155,7 @@ val customThemePatch = resourcePatch(
|
|||
"sthlm_blk", "sthlm_blk_grad_start",
|
||||
// Misc.
|
||||
"image_placeholder_color",
|
||||
-> backgroundColor
|
||||
-> backgroundColor
|
||||
|
||||
// "About the artist" background color in song player.
|
||||
"gray_15",
|
||||
|
|
@ -164,17 +164,17 @@ val customThemePatch = resourcePatch(
|
|||
// Playlist list background in home page.
|
||||
"opacity_white_10",
|
||||
// "What's New" pills background.
|
||||
"dark_base_background_tinted_highlight"
|
||||
-> backgroundColorSecondary
|
||||
"dark_base_background_tinted_highlight",
|
||||
-> backgroundColorSecondary
|
||||
|
||||
"dark_brightaccent_background_base",
|
||||
"dark_base_text_brightaccent",
|
||||
"green_light",
|
||||
"spotify_green_157"
|
||||
-> accentColor
|
||||
"spotify_green_157",
|
||||
-> accentColor
|
||||
|
||||
"dark_brightaccent_background_press"
|
||||
-> accentColorPressed
|
||||
"dark_brightaccent_background_press",
|
||||
-> accentColorPressed
|
||||
|
||||
else -> continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,31 @@
|
|||
package app.revanced.patches.spotify.layout.theme
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import app.revanced.util.containsLiteralInstruction
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val colorSpaceUtilsClassFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.colorSpaceUtilsClassMethod by gettingFirstMethodDeclaratively {
|
||||
strings("The specified color must be encoded in an RGB color space.") // Partial string match.
|
||||
}
|
||||
|
||||
internal val convertArgbToRgbaFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.convertArgbToRgbaMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC, AccessFlags.FINAL)
|
||||
returnType("J")
|
||||
parameterTypes("J")
|
||||
}
|
||||
|
||||
internal val parseLottieJsonFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.parseLottieJsonMethod by gettingFirstMethodDeclaratively {
|
||||
strings("Unsupported matte type: ")
|
||||
}
|
||||
|
||||
internal val parseAnimatedColorFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.parseAnimatedColorMethod by gettingFirstMethodDeclaratively {
|
||||
parameterTypes("L", "F")
|
||||
returnType("Ljava/lang/Object;")
|
||||
custom { method, _ ->
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package app.revanced.patches.spotify.misc.extension
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal val loadOrbitLibraryFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.loadOrbitLibraryMethod by gettingFirstMethodDeclaratively {
|
||||
strings("orbit_library_load", "orbit-jni-spotify")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ internal val loadOrbitLibraryHook = extensionHook {
|
|||
// FIXME: Creating this is a mess and needs refactoring.
|
||||
extensionHook(
|
||||
getInsertIndex = {
|
||||
loadOrbitLibraryFingerprint.stringMatches.last().index
|
||||
loadOrbitLibraryMethod.stringMatches.last().index
|
||||
},
|
||||
getContextRegister = { method ->
|
||||
val contextReferenceIndex = method.indexOfFirstInstruction {
|
||||
|
|
@ -25,6 +25,6 @@ internal val loadOrbitLibraryHook = extensionHook {
|
|||
|
||||
"v$contextRegister"
|
||||
},
|
||||
fingerprint = loadOrbitLibraryFingerprint,
|
||||
fingerprint = loadOrbitLibraryMethod,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,21 @@
|
|||
package app.revanced.patches.spotify.misc.fix.login
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.literal
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import app.revanced.util.literal
|
||||
|
||||
internal val katanaProxyLoginMethodHandlerClassFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.katanaProxyLoginMethodHandlerClassMethod by gettingFirstMethodDeclaratively {
|
||||
strings("katana_proxy_auth")
|
||||
}
|
||||
|
||||
internal val katanaProxyLoginMethodTryAuthorizeFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.katanaProxyLoginMethodTryAuthorizeMethod by gettingFirstMethodDeclaratively {
|
||||
strings("e2e")
|
||||
literal { 0 }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import app.revanced.util.returnEarly
|
|||
@Suppress("unused")
|
||||
val `Fix Facebook login` by creatingBytecodePatch(
|
||||
description =
|
||||
"Fix logging in with Facebook when the app is patched by always opening the login in a web browser window.",
|
||||
"Fix logging in with Facebook when the app is patched by always opening the login in a web browser window.",
|
||||
) {
|
||||
compatibleWith("com.spotify.music")
|
||||
|
||||
|
|
@ -17,10 +17,10 @@ val `Fix Facebook login` by creatingBytecodePatch(
|
|||
// Override the Facebook SDK to always handle the login using the web browser, which does not perform
|
||||
// signature checks.
|
||||
|
||||
val katanaProxyLoginMethodHandlerClass = katanaProxyLoginMethodHandlerClassFingerprint.originalClassDef
|
||||
val katanaProxyLoginMethodHandlerClass = katanaProxyLoginMethodHandlerClassMethod.originalClassDef
|
||||
// Always return 0 (no Intent was launched) as the result of trying to authorize with the Facebook app to
|
||||
// make the login fallback to a web browser window.
|
||||
katanaProxyLoginMethodTryAuthorizeFingerprint
|
||||
katanaProxyLoginMethodTryAuthorizeMethod
|
||||
.match(katanaProxyLoginMethodHandlerClass)
|
||||
.method
|
||||
.returnEarly(0)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package app.revanced.patches.spotify.misc.lyrics
|
|||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.extensions.replaceInstruction
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
import app.revanced.patcher.patch.stringOption
|
||||
import app.revanced.util.getReference
|
||||
|
|
@ -60,7 +59,7 @@ val `Change lyrics provider` by creatingBytecodePatch(
|
|||
}
|
||||
|
||||
apply {
|
||||
val httpClientBuilderMethod = httpClientBuilderFingerprint.originalMethod
|
||||
val httpClientBuilderMethod = httpClientBuilderMethod.originalMethod
|
||||
|
||||
// region Create a modified copy of the HTTP client builder method with the custom lyrics provider host.
|
||||
|
||||
|
|
@ -83,7 +82,7 @@ val `Change lyrics provider` by creatingBytecodePatch(
|
|||
)
|
||||
|
||||
// Add the patched method to the class.
|
||||
httpClientBuilderFingerprint.classDef.methods.add(this)
|
||||
httpClientBuilderMethod.classDef.methods.add(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,18 @@
|
|||
package app.revanced.patches.spotify.misc.lyrics
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal val httpClientBuilderFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.httpClientBuilderMethod by gettingFirstMethodDeclaratively {
|
||||
strings("client == null", "scheduler == null")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,18 @@
|
|||
package app.revanced.patches.spotify.misc.privacy
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val shareCopyUrlFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.shareCopyUrlMethod by gettingFirstMethodDeclaratively {
|
||||
returnType("Ljava/lang/Object;")
|
||||
parameterTypes("Ljava/lang/Object;")
|
||||
strings("clipboard", "Spotify Link")
|
||||
|
|
@ -14,7 +21,7 @@ internal val shareCopyUrlFingerprint = fingerprint {
|
|||
}
|
||||
}
|
||||
|
||||
internal val oldShareCopyUrlFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.oldShareCopyUrlMethod by gettingFirstMethodDeclaratively {
|
||||
returnType("Ljava/lang/Object;")
|
||||
parameterTypes("Ljava/lang/Object;")
|
||||
strings("clipboard", "createNewSession failed")
|
||||
|
|
@ -23,7 +30,7 @@ internal val oldShareCopyUrlFingerprint = fingerprint {
|
|||
}
|
||||
}
|
||||
|
||||
internal val formatAndroidShareSheetUrlFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.formatAndroidShareSheetUrlMethod by gettingFirstMethodDeclaratively {
|
||||
returnType("Ljava/lang/String;")
|
||||
parameterTypes("L", "Ljava/lang/String;")
|
||||
opcodes(
|
||||
|
|
@ -38,7 +45,7 @@ internal val formatAndroidShareSheetUrlFingerprint = fingerprint {
|
|||
}
|
||||
}
|
||||
|
||||
internal val oldFormatAndroidShareSheetUrlFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.oldFormatAndroidShareSheetUrlMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC)
|
||||
returnType("Ljava/lang/String;")
|
||||
parameterTypes("Lcom/spotify/share/social/sharedata/ShareData;", "Ljava/lang/String;")
|
||||
|
|
|
|||
|
|
@ -24,12 +24,12 @@ val `Sanitize sharing links` by creatingBytecodePatch(
|
|||
|
||||
apply {
|
||||
val extensionMethodDescriptor = "$EXTENSION_CLASS_DESCRIPTOR->" +
|
||||
"sanitizeSharingLink(Ljava/lang/String;)Ljava/lang/String;"
|
||||
"sanitizeSharingLink(Ljava/lang/String;)Ljava/lang/String;"
|
||||
|
||||
val copyFingerprint = if (shareCopyUrlFingerprint.originalMethodOrNull != null) {
|
||||
shareCopyUrlFingerprint
|
||||
val copyFingerprint = if (shareCopyUrlMethod.originalMethodOrNull != null) {
|
||||
shareCopyUrlMethod
|
||||
} else {
|
||||
oldShareCopyUrlFingerprint
|
||||
oldShareCopyUrlMethod
|
||||
}
|
||||
|
||||
copyFingerprint.method.apply {
|
||||
|
|
@ -43,14 +43,14 @@ val `Sanitize sharing links` by creatingBytecodePatch(
|
|||
"""
|
||||
invoke-static { v$urlRegister }, $extensionMethodDescriptor
|
||||
move-result-object v$urlRegister
|
||||
"""
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
// Android native share sheet is used for all other quick share types (X, WhatsApp, etc).
|
||||
val shareUrlParameter: String
|
||||
val shareSheetFingerprint = if (formatAndroidShareSheetUrlFingerprint.originalMethodOrNull != null) {
|
||||
val methodAccessFlags = formatAndroidShareSheetUrlFingerprint.originalMethod
|
||||
val shareSheetFingerprint = if (formatAndroidShareSheetUrlMethod.originalMethodOrNull != null) {
|
||||
val methodAccessFlags = formatAndroidShareSheetUrlMethod.originalMethod
|
||||
shareUrlParameter = if (AccessFlags.STATIC.isSet(methodAccessFlags.accessFlags)) {
|
||||
// In newer implementations the method is static, so p0 is not `this`.
|
||||
"p1"
|
||||
|
|
@ -60,10 +60,10 @@ val `Sanitize sharing links` by creatingBytecodePatch(
|
|||
"p2"
|
||||
}
|
||||
|
||||
formatAndroidShareSheetUrlFingerprint
|
||||
formatAndroidShareSheetUrlMethod
|
||||
} else {
|
||||
shareUrlParameter = "p2"
|
||||
oldFormatAndroidShareSheetUrlFingerprint
|
||||
oldFormatAndroidShareSheetUrlMethod
|
||||
}
|
||||
|
||||
shareSheetFingerprint.method.addInstructions(
|
||||
|
|
@ -71,7 +71,7 @@ val `Sanitize sharing links` by creatingBytecodePatch(
|
|||
"""
|
||||
invoke-static { $shareUrlParameter }, $extensionMethodDescriptor
|
||||
move-result-object $shareUrlParameter
|
||||
"""
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,16 @@
|
|||
package app.revanced.patches.spotify.misc.widgets
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val canBindAppWidgetPermissionFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.canBindAppWidgetPermissionMethod by gettingFirstMethodDeclaratively {
|
||||
strings("android.permission.BIND_APPWIDGET")
|
||||
opcodes(Opcode.AND_INT_LIT8)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,6 @@ val `Fix third party launchers widgets` by creatingBytecodePatch(
|
|||
// Only system app launchers are granted the BIND_APPWIDGET permission.
|
||||
// Override the method that checks for it to always return true, as this permission is not actually required
|
||||
// for the widgets to work.
|
||||
canBindAppWidgetPermissionFingerprint.method.returnEarly(true)
|
||||
canBindAppWidgetPermissionMethod.returnEarly(true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
package app.revanced.patches.spotify.shared
|
||||
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
|
|
|||
|
|
@ -1,20 +1,18 @@
|
|||
package app.revanced.patches.strava.mediaupload
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal val getCompressionQualityFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.getCompressionQualityMethod by gettingFirstMethodDeclaratively {
|
||||
custom { method, _ ->
|
||||
method.name == "getCompressionQuality"
|
||||
}
|
||||
}
|
||||
|
||||
internal val getMaxDurationFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.getMaxDurationMethod by gettingFirstMethodDeclaratively {
|
||||
custom { method, _ ->
|
||||
method.name == "getMaxDuration"
|
||||
}
|
||||
}
|
||||
|
||||
internal val getMaxSizeFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.getMaxSizeMethod by gettingFirstMethodDeclaratively {
|
||||
custom { method, _ ->
|
||||
method.name == "getMaxSize"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,15 +31,15 @@ val `Overwrite media upload parameters` by creatingBytecodePatch(
|
|||
val mediaUploadParametersClass = firstClassDef { type.endsWith("/MediaUploadParameters;") }
|
||||
|
||||
compressionQuality?.let { compressionQuality ->
|
||||
getCompressionQualityFingerprint.match(mediaUploadParametersClass).method.returnEarly(compressionQuality / 100f)
|
||||
getCompressionQualityMethod.match(mediaUploadParametersClass).method.returnEarly(compressionQuality / 100f)
|
||||
}
|
||||
|
||||
maxDuration?.let { maxDuration ->
|
||||
getMaxDurationFingerprint.match(mediaUploadParametersClass).method.returnEarly(maxDuration)
|
||||
getMaxDurationMethod.match(mediaUploadParametersClass).method.returnEarly(maxDuration)
|
||||
}
|
||||
|
||||
maxSize?.let {
|
||||
getMaxSizeFingerprint.match(mediaUploadParametersClass).method.returnEarly(it)
|
||||
getMaxSizeMethod.match(mediaUploadParametersClass).method.returnEarly(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,23 @@
|
|||
package app.revanced.patches.ticktick.misc.themeunlock
|
||||
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.gettingFirstMutableMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
||||
internal val BytecodePatchContext.checkLockedThemesFingerprint by gettingFirstMutableMethodDeclaratively {
|
||||
name("isLockedTheme")
|
||||
definingClass("Theme;"::endsWith)
|
||||
}
|
||||
|
||||
internal val BytecodePatchContext.setThemeFingerprint by gettingFirstMutableMethodDeclaratively {
|
||||
internal val BytecodePatchContext.setThemeMethod by gettingFirstMutableMethodDeclaratively {
|
||||
name("lambda\$updateUserBtn\$1")
|
||||
definingClass("ThemePreviewActivity;"::endsWith)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,6 @@ val `Unlock themes` by creatingBytecodePatch(
|
|||
""",
|
||||
)
|
||||
|
||||
setThemeFingerprint.removeInstructions(0, 10)
|
||||
setThemeMethod.removeInstructions(0, 10)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import app.revanced.patcher.extensions.instructions
|
|||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
import app.revanced.patches.tiktok.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.tiktok.misc.settings.Settings
|
||||
import app.revanced.patches.tiktok.misc.settings.settingsStatusLoadFingerprint
|
||||
import app.revanced.patches.tiktok.misc.settings.settingsStatusLoadMethod
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/tiktok/f
|
|||
@Suppress("unused")
|
||||
val `Feed filter` by creatingBytecodePatch(
|
||||
description = "Removes ads, livestreams, stories, image videos " +
|
||||
"and videos with a specific amount of views or likes from the feed.",
|
||||
"and videos with a specific amount of views or likes from the feed.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
|
|
@ -29,20 +29,19 @@ val `Feed filter` by creatingBytecodePatch(
|
|||
apply {
|
||||
arrayOf(
|
||||
feedApiServiceLIZMethod to "$EXTENSION_CLASS_DESCRIPTOR->filter(Lcom/ss/android/ugc/aweme/feed/model/FeedItemList;)V",
|
||||
followFeedMethod to "$EXTENSION_CLASS_DESCRIPTOR->filter(Lcom/ss/android/ugc/aweme/follow/presenter/FollowFeedList;)V"
|
||||
followFeedMethod to "$EXTENSION_CLASS_DESCRIPTOR->filter(Lcom/ss/android/ugc/aweme/follow/presenter/FollowFeedList;)V",
|
||||
).forEach { (method, filterSignature) ->
|
||||
val returnInstruction = method.instructions.first { it.opcode == Opcode.RETURN_OBJECT }
|
||||
val register = (returnInstruction as OneRegisterInstruction).registerA
|
||||
method.addInstruction(
|
||||
returnInstruction.location.index,
|
||||
"invoke-static { v$register }, $filterSignature"
|
||||
"invoke-static { v$register }, $filterSignature",
|
||||
)
|
||||
}
|
||||
|
||||
settingsStatusLoadFingerprint.method.addInstruction(
|
||||
settingsStatusLoadMethod.addInstruction(
|
||||
0,
|
||||
"invoke-static {}, Lapp/revanced/extension/tiktok/settings/SettingsStatus;->enableFeedFilter()V",
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import app.revanced.patcher.extensions.addInstructions
|
|||
import app.revanced.patcher.extensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
import app.revanced.patches.tiktok.shared.onRenderFirstFrameFingerprint
|
||||
import app.revanced.patches.tiktok.shared.onRenderFirstFrameMethod
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
|
|
@ -29,7 +29,7 @@ val `Remember clear display` by creatingBytecodePatch(
|
|||
addInstructions(
|
||||
isEnabledIndex,
|
||||
"invoke-static { v$isEnabledRegister }, " +
|
||||
"Lapp/revanced/extension/tiktok/cleardisplay/RememberClearDisplayPatch;->rememberClearDisplayState(Z)V",
|
||||
"Lapp/revanced/extension/tiktok/cleardisplay/RememberClearDisplayPatch;->rememberClearDisplayState(Z)V",
|
||||
)
|
||||
|
||||
// endregion
|
||||
|
|
@ -37,7 +37,7 @@ val `Remember clear display` by creatingBytecodePatch(
|
|||
// region Override the "Clear display" configuration load event to load the state of clear display.
|
||||
|
||||
val clearDisplayEventClass = parameters[0].type
|
||||
onRenderFirstFrameFingerprint.method.addInstructionsWithLabels(
|
||||
onRenderFirstFrameMethod.addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
# Create a new clearDisplayEvent and post it to the EventBus (https://github.com/greenrobot/EventBus)
|
||||
|
|
@ -60,7 +60,7 @@ val `Remember clear display` by creatingBytecodePatch(
|
|||
invoke-direct { v0, v1, v2, v3, v4 }, $clearDisplayEventClass-><init>(ILjava/lang/String;Ljava/lang/String;Z)V
|
||||
invoke-virtual { v0 }, $clearDisplayEventClass->post()Lcom/ss/android/ugc/governance/eventbus/IEvent;
|
||||
""",
|
||||
ExternalLabel("clear_display_disabled", onRenderFirstFrameFingerprint.method.getInstruction(0)),
|
||||
ExternalLabel("clear_display_disabled", onRenderFirstFrameMethod.getInstruction(0)),
|
||||
)
|
||||
|
||||
// endregion
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import app.revanced.patcher.extensions.*
|
|||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
import app.revanced.patches.tiktok.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.tiktok.misc.settings.Settings
|
||||
import app.revanced.patches.tiktok.misc.settings.settingsStatusLoadFingerprint
|
||||
import app.revanced.patches.tiktok.misc.settings.settingsStatusLoadMethod
|
||||
import app.revanced.util.findInstructionIndicesReversedOrThrow
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.returnEarly
|
||||
|
|
@ -70,7 +70,7 @@ val Downloads by creatingBytecodePatch(
|
|||
}
|
||||
}
|
||||
|
||||
settingsStatusLoadFingerprint.method.addInstruction(
|
||||
settingsStatusLoadMethod.addInstruction(
|
||||
0,
|
||||
"invoke-static {}, Lapp/revanced/extension/tiktok/settings/SettingsStatus;->enableDownload()V",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import app.revanced.patcher.extensions.addInstruction
|
|||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
import app.revanced.patches.tiktok.shared.getEnterFromFingerprint
|
||||
import app.revanced.patches.tiktok.shared.onRenderFirstFrameFingerprint
|
||||
import app.revanced.patches.tiktok.shared.getEnterFromMethod
|
||||
import app.revanced.patches.tiktok.shared.onRenderFirstFrameMethod
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.returnEarly
|
||||
|
|
@ -38,12 +38,12 @@ val `Playback speed` by creatingBytecodePatch(
|
|||
|
||||
// By default, the playback speed will reset to 1.0 at the start of each video.
|
||||
// Instead, override it with the desired playback speed.
|
||||
onRenderFirstFrameFingerprint.method.addInstructions(
|
||||
onRenderFirstFrameMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
# Video playback location (e.g. home page, following page or search result page) retrieved using getEnterFrom method.
|
||||
const/4 v0, 0x1
|
||||
invoke-virtual { p0, v0 }, ${getEnterFromFingerprint.originalMethod}
|
||||
invoke-virtual { p0, v0 }, ${getEnterFromMethod.originalMethod}
|
||||
move-result-object v0
|
||||
|
||||
# Model of current video retrieved using getCurrentAweme method.
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ val `Disable login requirement` by creatingBytecodePatch {
|
|||
|
||||
apply {
|
||||
listOf(
|
||||
mandatoryLoginServiceFingerprint,
|
||||
mandatoryLoginService2Fingerprint,
|
||||
mandatoryLoginServiceMethod,
|
||||
mandatoryLoginService2Method,
|
||||
).forEach { fingerprint ->
|
||||
fingerprint.method.addInstructions(
|
||||
0,
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
package app.revanced.patches.tiktok.misc.login.disablerequirement
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal val mandatoryLoginServiceFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.mandatoryLoginServiceMethod by gettingFirstMethodDeclaratively {
|
||||
custom { method, classDef ->
|
||||
classDef.endsWith("/MandatoryLoginService;") &&
|
||||
method.name == "enableForcedLogin"
|
||||
}
|
||||
}
|
||||
|
||||
internal val mandatoryLoginService2Fingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.mandatoryLoginService2Method by gettingFirstMethodDeclaratively {
|
||||
custom { method, classDef ->
|
||||
classDef.endsWith("/MandatoryLoginService;") &&
|
||||
method.name == "shouldShowForcedLogin"
|
||||
|
|
|
|||
|
|
@ -1,33 +1,31 @@
|
|||
package app.revanced.patches.tiktok.misc.settings
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal val addSettingsEntryFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.addSettingsEntryMethod by gettingFirstMethodDeclaratively {
|
||||
custom { method, classDef ->
|
||||
classDef.endsWith("/SettingNewVersionFragment;") &&
|
||||
method.name == "initUnitManger"
|
||||
}
|
||||
}
|
||||
|
||||
internal val adPersonalizationActivityOnCreateFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.adPersonalizationActivityOnCreateMethod by gettingFirstMethodDeclaratively {
|
||||
custom { method, classDef ->
|
||||
classDef.endsWith("/AdPersonalizationActivity;") &&
|
||||
method.name == "onCreate"
|
||||
}
|
||||
}
|
||||
|
||||
internal val settingsEntryFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.settingsEntryMethod by gettingFirstMethodDeclaratively {
|
||||
strings("pls pass item or extends the EventUnit")
|
||||
}
|
||||
|
||||
internal val settingsEntryInfoFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.settingsEntryInfoMethod by gettingFirstMethodDeclaratively {
|
||||
strings(
|
||||
"ExposeItem(title=",
|
||||
", icon=",
|
||||
)
|
||||
}
|
||||
|
||||
internal val settingsStatusLoadFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.settingsStatusLoadMethod by gettingFirstMethodDeclaratively {
|
||||
custom { method, classDef ->
|
||||
classDef.endsWith("Lapp/revanced/extension/tiktok/settings/SettingsStatus;") &&
|
||||
method.name == "load"
|
||||
|
|
|
|||
|
|
@ -28,23 +28,23 @@ val Settings by creatingBytecodePatch(
|
|||
apply {
|
||||
val initializeSettingsMethodDescriptor =
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->initialize(" +
|
||||
"Lcom/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity;" +
|
||||
")Z"
|
||||
"Lcom/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity;" +
|
||||
")Z"
|
||||
|
||||
val createSettingsEntryMethodDescriptor =
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->createSettingsEntry(" +
|
||||
"Ljava/lang/String;" +
|
||||
"Ljava/lang/String;" +
|
||||
")Ljava/lang/Object;"
|
||||
"Ljava/lang/String;" +
|
||||
"Ljava/lang/String;" +
|
||||
")Ljava/lang/Object;"
|
||||
|
||||
fun String.toClassName(): String = substring(1, this.length - 1).replace("/", ".")
|
||||
|
||||
// Find the class name of classes which construct a settings entry
|
||||
val settingsButtonClass = settingsEntryFingerprint.originalClassDef.type.toClassName()
|
||||
val settingsButtonInfoClass = settingsEntryInfoFingerprint.originalClassDef.type.toClassName()
|
||||
val settingsButtonClass = settingsEntryMethod.originalClassDef.type.toClassName()
|
||||
val settingsButtonInfoClass = settingsEntryInfoMethod.originalClassDef.type.toClassName()
|
||||
|
||||
// Create a settings entry for 'revanced settings' and add it to settings fragment
|
||||
addSettingsEntryFingerprint.method.apply {
|
||||
addSettingsEntryMethod.apply {
|
||||
val markIndex = implementation!!.instructions.indexOfFirst {
|
||||
it.opcode == Opcode.IGET_OBJECT && ((it as Instruction22c).reference as FieldReference).name == "headerUnit"
|
||||
}
|
||||
|
|
@ -67,13 +67,13 @@ val Settings by creatingBytecodePatch(
|
|||
const-string v1, "$settingsButtonInfoClass"
|
||||
invoke-static {v0, v1}, $createSettingsEntryMethodDescriptor
|
||||
move-result-object v0
|
||||
check-cast v0, ${settingsEntryFingerprint.originalClassDef.type}
|
||||
check-cast v0, ${settingsEntryMethod.originalClassDef.type}
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
// Initialize the settings menu once the replaced setting entry is clicked.
|
||||
adPersonalizationActivityOnCreateFingerprint.method.apply {
|
||||
adPersonalizationActivityOnCreateMethod.apply {
|
||||
val initializeSettingsIndex = implementation!!.instructions.indexOfFirst {
|
||||
it.opcode == Opcode.INVOKE_SUPER
|
||||
} + 1
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import app.revanced.patcher.extensions.getInstruction
|
|||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
import app.revanced.patches.tiktok.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.tiktok.misc.settings.Settings
|
||||
import app.revanced.patches.tiktok.misc.settings.settingsStatusLoadFingerprint
|
||||
import app.revanced.patches.tiktok.misc.settings.settingsStatusLoadMethod
|
||||
import app.revanced.util.findMutableMethodOf
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
|
@ -91,7 +91,7 @@ val `SIM spoof` by creatingBytecodePatch(
|
|||
}
|
||||
|
||||
// Enable patch in settings.
|
||||
settingsStatusLoadFingerprint.method.addInstruction(
|
||||
settingsStatusLoadMethod.addInstruction(
|
||||
0,
|
||||
"invoke-static {}, Lapp/revanced/extension/tiktok/settings/SettingsStatus;->enableSimSpoof()V",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,17 @@
|
|||
package app.revanced.patches.tiktok.shared
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val getEnterFromFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.getEnterFromMethod by gettingFirstMethodDeclaratively {
|
||||
returnType("Ljava/lang/String;")
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
parameterTypes("Z")
|
||||
|
|
@ -22,7 +29,7 @@ internal val getEnterFromFingerprint = fingerprint {
|
|||
}
|
||||
}
|
||||
|
||||
internal val onRenderFirstFrameFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.onRenderFirstFrameMethod by gettingFirstMethodDeclaratively {
|
||||
strings("method_enable_viewpager_preload_duration")
|
||||
custom { _, classDef ->
|
||||
classDef.endsWith("/BaseListFragmentPanel;")
|
||||
|
|
|
|||
|
|
@ -1,9 +1,16 @@
|
|||
package app.revanced.patches.tudortmund.lockscreen
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val brightnessFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.brightnessMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC)
|
||||
returnType("V")
|
||||
parameterTypes()
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ val `Show on lockscreen` by creatingBytecodePatch(
|
|||
compatibleWith("de.tudortmund.app")
|
||||
|
||||
apply {
|
||||
brightnessFingerprint.method.apply {
|
||||
brightnessMethod.apply {
|
||||
// Find the instruction where the brightness value is loaded into a register
|
||||
val brightnessInstruction = instructions.firstNotNullOf { instruction ->
|
||||
if (instruction.opcode != Opcode.IGET_OBJECT) return@firstNotNullOf null
|
||||
|
|
@ -61,10 +61,10 @@ val `Show on lockscreen` by creatingBytecodePatch(
|
|||
replaceInstruction(
|
||||
windowIndex,
|
||||
"invoke-static { v$activityRegister, v$brightnessRegister }, " +
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->" +
|
||||
"getWindow" +
|
||||
"(Landroidx/appcompat/app/AppCompatActivity;F)" +
|
||||
"Landroid/view/Window;",
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->" +
|
||||
"getWindow" +
|
||||
"(Landroidx/appcompat/app/AppCompatActivity;F)" +
|
||||
"Landroid/view/Window;",
|
||||
)
|
||||
|
||||
// Normally, the brightness is loaded into a register after the getWindow call.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ val `Disable blog notification reminder` by creatingBytecodePatch(
|
|||
compatibleWith("com.tumblr")
|
||||
|
||||
apply {
|
||||
isBlogNotifyEnabledFingerprint.method.addInstructions(
|
||||
isBlogNotifyEnabledMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
# Return false for BlogNotifyCtaDialog.isEnabled() method.
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
package app.revanced.patches.tumblr.annoyances.notifications
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
// The BlogNotifyCtaDialog asks you if you want to enable notifications for a blog.
|
||||
// It shows whenever you visit a certain blog for the second time and disables itself
|
||||
// if it was shown a total of 3 times (stored in app storage).
|
||||
// This targets the BlogNotifyCtaDialog.isEnabled() method to let it always return false.
|
||||
internal val isBlogNotifyEnabledFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.isBlogNotifyEnabledMethod by gettingFirstMethodDeclaratively {
|
||||
strings("isEnabled --> ", "blog_notify_enabled")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
package app.revanced.patches.tumblr.featureflags
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
|
|
@ -13,7 +20,7 @@ import com.android.tools.smali.dexlib2.Opcode
|
|||
// Some features seem to be very old and never removed, though, such as Google Login.
|
||||
// The startIndex of the opcode pattern is at the start of the function after the arg null check.
|
||||
// we want to insert our instructions there.
|
||||
internal val getFeatureValueFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.getFeatureValueMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returnType("Ljava/lang/String;")
|
||||
parameterTypes("L", "Z")
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ package app.revanced.patches.tumblr.featureflags
|
|||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||
import com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable
|
||||
|
||||
/**
|
||||
* Override a feature flag with a value.
|
||||
|
|
@ -24,15 +24,15 @@ val overrideFeatureFlagsPatch = bytecodePatch(
|
|||
) {
|
||||
|
||||
apply {
|
||||
val configurationClass = getFeatureValueFingerprint.originalMethod.definingClass
|
||||
val featureClass = getFeatureValueFingerprint.originalMethod.parameterTypes[0].toString()
|
||||
val configurationClass = getFeatureValueMethod.originalMethod.definingClass
|
||||
val featureClass = getFeatureValueMethod.originalMethod.parameterTypes[0].toString()
|
||||
|
||||
// The method we want to inject into does not have enough registers, so we inject a helper method
|
||||
// and inject more instructions into it later, see addOverride.
|
||||
// This is not in an extension since the unused variable would get compiled away and the method would
|
||||
// get compiled to only have one register, which is not enough for our later injected instructions.
|
||||
val helperMethod = ImmutableMethod(
|
||||
getFeatureValueFingerprint.originalMethod.definingClass,
|
||||
getFeatureValueMethod.originalMethod.definingClass,
|
||||
"getValueOverride",
|
||||
listOf(ImmutableMethodParameter(featureClass, null, "feature")),
|
||||
"Ljava/lang/String;",
|
||||
|
|
@ -62,15 +62,15 @@ val overrideFeatureFlagsPatch = bytecodePatch(
|
|||
""",
|
||||
)
|
||||
}.also { helperMethod ->
|
||||
getFeatureValueFingerprint.classDef.methods.add(helperMethod)
|
||||
getFeatureValueMethod.classDef.methods.add(helperMethod)
|
||||
}
|
||||
|
||||
// Here we actually insert the hook to call our helper method and return its value if it returns not null
|
||||
// This is equivalent to
|
||||
// String forcedValue = getValueOverride(feature)
|
||||
// if (forcedValue != null) return forcedValue
|
||||
val getFeatureIndex = getFeatureValueFingerprint.instructionMatches.first().index
|
||||
getFeatureValueFingerprint.method.addInstructionsWithLabels(
|
||||
val getFeatureIndex = getFeatureValueMethod.instructionMatches.first().index
|
||||
getFeatureValueMethod.addInstructionsWithLabels(
|
||||
getFeatureIndex,
|
||||
"""
|
||||
# Call the Helper Method with the Feature
|
||||
|
|
|
|||
|
|
@ -1,12 +1,19 @@
|
|||
package app.revanced.patches.tumblr.fixes
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
// Fingerprint for the addQueryParam method from retrofit2
|
||||
// https://github.com/square/retrofit/blob/trunk/retrofit/src/main/java/retrofit2/RequestBuilder.java#L186
|
||||
// Injecting here allows modifying dynamically set query parameters
|
||||
internal val addQueryParamFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.addQueryParamMethod by gettingFirstMethodDeclaratively {
|
||||
parameterTypes("Ljava/lang/String;", "Ljava/lang/String;", "Z")
|
||||
strings("Malformed URL. Base: ", ", Relative: ")
|
||||
}
|
||||
|
|
@ -14,7 +21,7 @@ internal val addQueryParamFingerprint = fingerprint {
|
|||
// Fingerprint for the parseHttpMethodAndPath method from retrofit2
|
||||
// https://github.com/square/retrofit/blob/ebf87b10997e2136af4d335276fa950221852c64/retrofit/src/main/java/retrofit2/RequestFactory.java#L270-L302
|
||||
// Injecting here allows modifying the path/query params of API endpoints defined via annotations
|
||||
internal val httpPathParserFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.httpPathParserMethod by gettingFirstMethodDeclaratively {
|
||||
opcodes(
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.IPUT_BOOLEAN,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import app.revanced.patcher.patch.creatingBytecodePatch
|
|||
@Suppress("unused")
|
||||
val `Fix old versions` by creatingBytecodePatch(
|
||||
description = "Fixes old versions of the app (v33.2 and earlier) breaking due to Tumblr removing remnants of Tumblr" +
|
||||
" Live from the API, which causes many requests to fail. This patch has no effect on newer versions of the app.",
|
||||
" Live from the API, which causes many requests to fail. This patch has no effect on newer versions of the app.",
|
||||
use = false,
|
||||
) {
|
||||
compatibleWith("com.tumblr")
|
||||
|
|
@ -19,8 +19,8 @@ val `Fix old versions` by creatingBytecodePatch(
|
|||
|
||||
// Remove the live query parameters from the path when it's specified via a @METHOD annotation.
|
||||
for (liveQueryParameter in liveQueryParameters) {
|
||||
httpPathParserFingerprint.method.addInstructions(
|
||||
httpPathParserFingerprint.instructionMatches.last().index + 1,
|
||||
httpPathParserMethod.addInstructions(
|
||||
httpPathParserMethod.instructionMatches.last().index + 1,
|
||||
"""
|
||||
# urlPath = urlPath.replace(liveQueryParameter, "")
|
||||
const-string p1, "$liveQueryParameter"
|
||||
|
|
@ -38,7 +38,7 @@ val `Fix old versions` by creatingBytecodePatch(
|
|||
// which would result in the path "api/me/inf0?fields[blog]=${value}"
|
||||
// Here we make sure that this value doesn't contain the broken query parameters.
|
||||
for (liveQueryParameter in liveQueryParameters) {
|
||||
addQueryParamFingerprint.method.addInstructions(
|
||||
addQueryParamMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
# queryParameterValue = queryParameterValue.replace(liveQueryParameter, "")
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ val filterTimelineObjectsPatch = bytecodePatch(
|
|||
dependsOn(sharedExtensionPatch)
|
||||
|
||||
apply {
|
||||
val filterInsertIndex = timelineFilterExtensionFingerprint.instructionMatches.first().index
|
||||
val filterInsertIndex = timelineFilterExtensionMethod.instructionMatches.first().index
|
||||
|
||||
timelineFilterExtensionFingerprint.method.apply {
|
||||
timelineFilterExtensionMethod.apply {
|
||||
val addInstruction = getInstruction<BuilderInstruction35c>(filterInsertIndex + 1)
|
||||
|
||||
val filterListRegister = addInstruction.registerC
|
||||
|
|
@ -48,8 +48,8 @@ val filterTimelineObjectsPatch = bytecodePatch(
|
|||
}
|
||||
|
||||
arrayOf(
|
||||
timelineConstructorFingerprint to 1,
|
||||
postsResponseConstructorFingerprint to 2,
|
||||
timelineConstructorMethod to 1,
|
||||
postsResponseConstructorMethod to 2,
|
||||
).forEach { (fingerprint, timelineObjectsRegister) ->
|
||||
fingerprint.method.addInstructions(
|
||||
0,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,19 @@
|
|||
package app.revanced.patches.tumblr.timelinefilter
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
// This is the constructor of the PostsResponse class.
|
||||
// The same applies here as with the TimelineConstructorFingerprint.
|
||||
internal val postsResponseConstructorFingerprint = fingerprint {
|
||||
// The same applies here as with the TimelineConstructorMethod.
|
||||
internal val BytecodePatchContext.postsResponseConstructorMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.CONSTRUCTOR, AccessFlags.PUBLIC)
|
||||
custom { method, classDef -> classDef.endsWith("/PostsResponse;") && method.parameters.size == 4 }
|
||||
}
|
||||
|
|
@ -14,7 +21,7 @@ internal val postsResponseConstructorFingerprint = fingerprint {
|
|||
// This is the constructor of the Timeline class.
|
||||
// It receives the List<TimelineObject> as an argument with a @Json annotation, so this should be the first time
|
||||
// that the List<TimelineObject> is exposed in non-library code.
|
||||
internal val timelineConstructorFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.timelineConstructorMethod by gettingFirstMethodDeclaratively {
|
||||
strings("timelineObjectsList")
|
||||
custom { method, classDef ->
|
||||
classDef.endsWith("/Timeline;") && method.parameters[0].type == "Ljava/util/List;"
|
||||
|
|
@ -24,7 +31,7 @@ internal val timelineConstructorFingerprint = fingerprint {
|
|||
// This fingerprints the extension TimelineFilterPatch.filterTimeline method.
|
||||
// The opcode fingerprint is searching for
|
||||
// if ("BLOCKED_OBJECT_DUMMY".equals(elementType)) iterator.remove();
|
||||
internal val timelineFilterExtensionFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.timelineFilterExtensionMethod by gettingFirstMethodDeclaratively {
|
||||
opcodes(
|
||||
Opcode.CONST_STRING, // "BLOCKED_OBJECT_DUMMY"
|
||||
Opcode.INVOKE_VIRTUAL, // HashSet.add(^)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package app.revanced.patches.twitch.misc.settings
|
||||
|
||||
import app.revanced.patcher.Fingerprint
|
||||
import app.revanced.patcher.extensions.ExternalLabel
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.addInstructionsWithLabels
|
||||
|
|
@ -98,9 +97,9 @@ val Settings by creatingBytecodePatch(
|
|||
name,
|
||||
MENU_ITEM_ENUM_CLASS_DESCRIPTOR,
|
||||
AccessFlags.PUBLIC.value or
|
||||
AccessFlags.FINAL.value or
|
||||
AccessFlags.ENUM.value or
|
||||
AccessFlags.STATIC.value,
|
||||
AccessFlags.FINAL.value or
|
||||
AccessFlags.ENUM.value or
|
||||
AccessFlags.STATIC.value,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,17 @@
|
|||
package app.revanced.patches.twitter.interaction.downloads
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val buildMediaOptionsSheetFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.buildMediaOptionsSheetMethod by gettingFirstMethodDeclaratively {
|
||||
opcodes(
|
||||
Opcode.IF_EQ,
|
||||
Opcode.SGET_OBJECT,
|
||||
|
|
@ -14,12 +21,12 @@ internal val buildMediaOptionsSheetFingerprint = fingerprint {
|
|||
strings("mediaEntity", "media_options_sheet")
|
||||
}
|
||||
|
||||
internal val constructMediaOptionsSheetFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.constructMediaOptionsSheetMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
strings("captionsState")
|
||||
}
|
||||
|
||||
internal val showDownloadVideoUpsellBottomSheetFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.showDownloadVideoUpsellBottomSheetMethod by gettingFirstMethodDeclaratively {
|
||||
returnType("Z")
|
||||
strings("mediaEntity", "url")
|
||||
opcodes(Opcode.IF_EQZ)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package app.revanced.patches.twitter.interaction.downloads
|
||||
|
||||
import app.revanced.patcher.Fingerprint
|
||||
import app.revanced.patcher.extensions.*
|
||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
|
@ -20,7 +19,7 @@ val `Unlock downloads` by creatingBytecodePatch(
|
|||
}
|
||||
|
||||
// Allow downloads for non-premium users.
|
||||
showDownloadVideoUpsellBottomSheetFingerprint.patch {
|
||||
showDownloadVideoUpsellBottomSheetMethod.patch {
|
||||
val checkIndex = instructionMatches.first().index
|
||||
val register = method.getInstruction<OneRegisterInstruction>(checkIndex).registerA
|
||||
|
||||
|
|
@ -28,7 +27,7 @@ val `Unlock downloads` by creatingBytecodePatch(
|
|||
}
|
||||
|
||||
// Force show the download menu item.
|
||||
constructMediaOptionsSheetFingerprint.patch {
|
||||
constructMediaOptionsSheetMethod.patch {
|
||||
val showDownloadButtonIndex = method.instructions.lastIndex - 1
|
||||
val register = method.getInstruction<TwoRegisterInstruction>(showDownloadButtonIndex).registerA
|
||||
|
||||
|
|
@ -36,7 +35,7 @@ val `Unlock downloads` by creatingBytecodePatch(
|
|||
}
|
||||
|
||||
// Make GIFs downloadable.
|
||||
buildMediaOptionsSheetFingerprint.let {
|
||||
buildMediaOptionsSheetMethod.let {
|
||||
it.method.apply {
|
||||
val checkMediaTypeIndex = it.instructionMatches.first().index
|
||||
val checkMediaTypeInstruction = getInstruction<TwoRegisterInstruction>(checkMediaTypeIndex)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ internal val domainNameOption = stringOption(
|
|||
InetAddress.getByName(it)
|
||||
} catch (_: UnknownHostException) {
|
||||
Logger.getLogger(this::class.java.name).warning(
|
||||
"Host \"$it\" did not resolve to any domain."
|
||||
"Host \"$it\" did not resolve to any domain.",
|
||||
)
|
||||
} catch (_: Exception) {
|
||||
// Must ignore any kind of exception. Trying to resolve network
|
||||
|
|
@ -61,7 +61,7 @@ internal val changeLinkSharingDomainResourcePatch = resourcePatch {
|
|||
@Suppress("unused")
|
||||
val `Change link sharing domain` by creatingBytecodePatch(
|
||||
description = "Replaces the domain name of shared links. Using this patch can prevent making posts that quote other posts.",
|
||||
use = false
|
||||
use = false,
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
|
|
@ -71,28 +71,28 @@ val `Change link sharing domain` by creatingBytecodePatch(
|
|||
"com.twitter.android"(
|
||||
"10.60.0-release.0",
|
||||
"10.86.0-release.0",
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
val domainName by domainNameOption()
|
||||
|
||||
apply {
|
||||
// Replace the domain name in the link sharing extension methods.
|
||||
linkSharingDomainHelperFingerprint.method.returnEarly(domainName!!)
|
||||
linkSharingDomainHelperMethod.returnEarly(domainName!!)
|
||||
|
||||
// Replace the domain name when copying a link with "Copy link" button.
|
||||
linkBuilderFingerprint.method.addInstructions(
|
||||
linkBuilderMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static { p0, p1, p2 }, $EXTENSION_CLASS_DESCRIPTOR->formatLink(JLjava/lang/String;)Ljava/lang/String;
|
||||
move-result-object p0
|
||||
return-object p0
|
||||
"""
|
||||
""",
|
||||
)
|
||||
|
||||
// TODO remove this once changeLinkSharingDomainResourcePatch is restored
|
||||
// Replace the domain name in the "Share via..." dialog.
|
||||
linkResourceGetterFingerprint.method.apply {
|
||||
linkResourceGetterMethod.apply {
|
||||
val templateIdConstIndex = indexOfFirstInstructionOrThrow(Opcode.CONST)
|
||||
|
||||
// Format the link with the new domain name register (1 instruction below the const).
|
||||
|
|
@ -103,7 +103,7 @@ val `Change link sharing domain` by creatingBytecodePatch(
|
|||
replaceInstruction(
|
||||
formatLinkCallIndex,
|
||||
"invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->" +
|
||||
"formatResourceLink([Ljava/lang/Object;)Ljava/lang/String;",
|
||||
"formatResourceLink([Ljava/lang/Object;)Ljava/lang/String;",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,28 @@
|
|||
package app.revanced.patches.twitter.misc.links
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val sanitizeSharingLinksFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.sanitizeSharingLinksMethod by gettingFirstMethodDeclaratively {
|
||||
returnType("Ljava/lang/String;")
|
||||
strings("<this>", "shareParam", "sessionToken")
|
||||
}
|
||||
|
||||
// Returns a shareable link string based on a tweet ID and a username.
|
||||
internal val linkBuilderFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.linkBuilderMethod by gettingFirstMethodDeclaratively {
|
||||
strings("/%1\$s/status/%2\$d")
|
||||
}
|
||||
|
||||
// TODO remove this once changeLinkSharingDomainResourcePatch is restored
|
||||
// Returns a shareable link for the "Share via..." dialog.
|
||||
internal val linkResourceGetterFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.linkResourceGetterMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
parameterTypes("Landroid/content/res/Resources;")
|
||||
custom { _, classDef ->
|
||||
|
|
@ -25,7 +32,7 @@ internal val linkResourceGetterFingerprint = fingerprint {
|
|||
}
|
||||
}
|
||||
|
||||
internal val linkSharingDomainHelperFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.linkSharingDomainHelperMethod by gettingFirstMethodDeclaratively {
|
||||
custom { method, classDef ->
|
||||
method.name == "getShareDomain" && classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ val `Sanitize sharing links` by creatingBytecodePatch(
|
|||
"com.twitter.android"(
|
||||
"10.60.0-release.0",
|
||||
"10.86.0-release.0",
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
apply {
|
||||
sanitizeSharingLinksFingerprint.method.addInstructions(
|
||||
sanitizeSharingLinksMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
# Method takes in a link (string, param 0) and then appends the tracking query params,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package app.revanced.patches.viber.ads
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal val findAdStringFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.findAdStringMethod by gettingFirstMethodDeclaratively {
|
||||
strings("viber_plus_debug_ads_free_flag")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package app.revanced.patches.viber.ads
|
||||
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||
import app.revanced.util.returnEarly
|
||||
|
|
@ -16,10 +15,10 @@ val `Hide Ads` by creatingBytecodePatch(
|
|||
compatibleWith("com.viber.voip"("25.9.2.0", "26.1.2.0"))
|
||||
|
||||
apply {
|
||||
val method = findAdStringFingerprint.method
|
||||
val method = findAdStringMethod
|
||||
|
||||
// Find the ads free string index
|
||||
val stringIndex = findAdStringFingerprint.stringMatches.first().index
|
||||
val stringIndex = findAdStringMethod.stringMatches.first().index
|
||||
|
||||
// Search backwards from the string to find the `new-instance` (TypeReference) instruction
|
||||
val typeRefIndex =
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
package app.revanced.patches.viber.misc.navbar
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
||||
internal val tabIdClassFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.tabIdClassMethod by gettingFirstMethodDeclaratively {
|
||||
strings("shouldShowTabId")
|
||||
}
|
||||
|
||||
|
|
@ -11,6 +17,6 @@ internal val shouldShowTabIdMethodFingerprint get() = fingerprint {
|
|||
parameterTypes("I", "I")
|
||||
returnType("Z")
|
||||
custom { methodDef, classDef ->
|
||||
classDef == tabIdClassFingerprint.classDef
|
||||
classDef == tabIdClassMethod.classDef
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
package app.revanced.patches.youtube.ad.general
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import app.revanced.util.containsLiteralInstruction
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionReversed
|
||||
|
|
@ -8,7 +15,7 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
|||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal val fullScreenEngagementAdContainerFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.fullScreenEngagementAdContainerMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returnType("V")
|
||||
parameterTypes()
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ val `Hide ads` by creatingBytecodePatch(
|
|||
apply {
|
||||
// Hide end screen store banner.
|
||||
|
||||
fullScreenEngagementAdContainerFingerprint.method.apply {
|
||||
fullScreenEngagementAdContainerMethod.apply {
|
||||
val addListIndex = indexOfAddListInstruction(this)
|
||||
val addListInstruction = getInstruction<FiveRegisterInstruction>(addListIndex)
|
||||
val listRegister = addListInstruction.registerC
|
||||
|
|
|
|||
|
|
@ -1,10 +1,17 @@
|
|||
package app.revanced.patches.youtube.ad.getpremium
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val getPremiumViewFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.getPremiumViewMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PROTECTED, AccessFlags.FINAL)
|
||||
returnType("V")
|
||||
parameterTypes("I", "I")
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ val hideGetPremiumPatch = bytecodePatch(
|
|||
"20.14.43",
|
||||
"20.21.37",
|
||||
"20.31.40",
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
apply {
|
||||
|
|
@ -39,8 +39,8 @@ val hideGetPremiumPatch = bytecodePatch(
|
|||
SwitchPreference("revanced_hide_get_premium"),
|
||||
)
|
||||
|
||||
getPremiumViewFingerprint.method.apply {
|
||||
val startIndex = getPremiumViewFingerprint.instructionMatches.first().index
|
||||
getPremiumViewMethod.apply {
|
||||
val startIndex = getPremiumViewMethod.instructionMatches.first().index
|
||||
val measuredWidthRegister = getInstruction<TwoRegisterInstruction>(startIndex).registerA
|
||||
val measuredHeightInstruction = getInstruction<TwoRegisterInstruction>(startIndex + 1)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package app.revanced.patches.youtube.ad.video
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal val loadVideoAdsFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.loadVideoAdsMethod by gettingFirstMethodDeclaratively {
|
||||
strings(
|
||||
"TriggerBundle doesn't have the required metadata specified by the trigger ",
|
||||
"Ping migration no associated ping bindings for activated trigger: ",
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ val `Video ads` by creatingBytecodePatch(
|
|||
"20.14.43",
|
||||
"20.21.37",
|
||||
"20.31.40",
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
apply {
|
||||
|
|
@ -36,7 +36,7 @@ val `Video ads` by creatingBytecodePatch(
|
|||
SwitchPreference("revanced_hide_video_ads"),
|
||||
)
|
||||
|
||||
loadVideoAdsFingerprint.method.addInstructionsWithLabels(
|
||||
loadVideoAdsMethod.addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static { }, Lapp/revanced/extension/youtube/patches/VideoAdsPatch;->shouldShowAds()Z
|
||||
|
|
@ -44,7 +44,7 @@ val `Video ads` by creatingBytecodePatch(
|
|||
if-nez v0, :show_video_ads
|
||||
return-void
|
||||
""",
|
||||
ExternalLabel("show_video_ads", loadVideoAdsFingerprint.method.getInstruction(0)),
|
||||
ExternalLabel("show_video_ads", loadVideoAdsMethod.getInstruction(0)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,16 @@
|
|||
package app.revanced.patches.youtube.interaction.dialog
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.methodCall
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
||||
internal val createDialogFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.createDialogMethod by gettingFirstMethodDeclaratively {
|
||||
returnType("V")
|
||||
parameterTypes("L", "L", "Ljava/lang/String;")
|
||||
instructions(
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR =
|
|||
|
||||
val `Remove viewer discretion dialog` by creatingBytecodePatch(
|
||||
description = "Adds an option to remove the dialog that appears when opening a video that has been age-restricted " +
|
||||
"by accepting it automatically. This does not bypass the age restriction.",
|
||||
"by accepting it automatically. This does not bypass the age restriction.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
|
|
@ -30,7 +30,7 @@ val `Remove viewer discretion dialog` by creatingBytecodePatch(
|
|||
"20.14.43",
|
||||
"20.21.37",
|
||||
"20.31.40",
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
apply {
|
||||
|
|
@ -40,7 +40,7 @@ val `Remove viewer discretion dialog` by creatingBytecodePatch(
|
|||
SwitchPreference("revanced_remove_viewer_discretion_dialog"),
|
||||
)
|
||||
|
||||
createDialogFingerprint.let {
|
||||
createDialogMethod.let {
|
||||
it.method.apply {
|
||||
val showDialogIndex = it.instructionMatches.last().index // TODO
|
||||
val dialogRegister = getInstruction<FiveRegisterInstruction>(showDialogIndex).registerC
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package app.revanced.patches.youtube.interaction.doubletap
|
||||
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
|
|
@ -57,7 +56,7 @@ val `Disable double tap actions` by creatingBytecodePatch(
|
|||
val doubleTapInfoGetSeekSourceFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
parameterTypes("Z")
|
||||
returnType(seekTypeEnumFingerprint.originalClassDef.type)
|
||||
returnType(seekTypeEnumMethod.originalClassDef.type)
|
||||
opcodes(
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.SGET_OBJECT,
|
||||
|
|
@ -79,7 +78,7 @@ val `Disable double tap actions` by creatingBytecodePatch(
|
|||
""",
|
||||
)
|
||||
|
||||
doubleTapInfoCtorFingerprint.match(
|
||||
doubleTapInfoCtorMethod.match(
|
||||
doubleTapInfoGetSeekSourceFingerprint.classDef,
|
||||
).method.addInstructions(
|
||||
0,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,16 @@
|
|||
package app.revanced.patches.youtube.interaction.doubletap
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val seekTypeEnumFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.seekTypeEnumMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)
|
||||
strings(
|
||||
"SEEK_SOURCE_SEEK_TO_NEXT_CHAPTER",
|
||||
|
|
@ -11,7 +18,7 @@ internal val seekTypeEnumFingerprint = fingerprint {
|
|||
)
|
||||
}
|
||||
|
||||
internal val doubleTapInfoCtorFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.doubleTapInfoCtorMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
parameterTypes(
|
||||
"Landroid/view/MotionEvent;",
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ internal const val BUTTON_DESCRIPTOR = "Lapp/revanced/extension/youtube/videopla
|
|||
@Suppress("unused")
|
||||
val Downloads by creatingBytecodePatch(
|
||||
description = "Adds support to download videos with an external downloader app " +
|
||||
"using the in-app download button or a video player action button.",
|
||||
"using the in-app download button or a video player action button.",
|
||||
) {
|
||||
dependsOn(
|
||||
downloadsResourcePatch,
|
||||
|
|
@ -76,7 +76,7 @@ val Downloads by creatingBytecodePatch(
|
|||
"20.14.43",
|
||||
"20.21.37",
|
||||
"20.31.40",
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
apply {
|
||||
|
|
@ -86,10 +86,10 @@ val Downloads by creatingBytecodePatch(
|
|||
// Main activity is used to launch downloader intent.
|
||||
mainActivityOnCreateMethod.addInstruction(
|
||||
0,
|
||||
"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",
|
||||
)
|
||||
|
||||
offlineVideoEndpointFingerprint.method.apply {
|
||||
offlineVideoEndpointMethod.apply {
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -1,10 +1,17 @@
|
|||
package app.revanced.patches.youtube.interaction.downloads
|
||||
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.addString
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val offlineVideoEndpointFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.offlineVideoEndpointMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returnType("V")
|
||||
parameterTypes(
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package app.revanced.patches.youtube.interaction.seekbar
|
||||
|
||||
import app.revanced.patcher.extensions.ExternalLabel
|
||||
import app.revanced.patcher.extensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.extensions.ExternalLabel
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
|
|
@ -34,30 +34,32 @@ val enableSeekbarTappingPatch = bytecodePatch(
|
|||
)
|
||||
|
||||
// Find the required methods to tap the seekbar.
|
||||
val seekbarTappingMethods = onTouchEventHandlerFingerprint.let {
|
||||
val seekbarTappingMethods = onTouchEventHandlerMethod.let {
|
||||
fun getReference(index: Int) = it.method.getInstruction<ReferenceInstruction>(index)
|
||||
.reference as MethodReference
|
||||
|
||||
listOf(
|
||||
getReference(it.instructionMatches.first().index),
|
||||
getReference(it.instructionMatches.last().index)
|
||||
getReference(it.instructionMatches.last().index),
|
||||
)
|
||||
}
|
||||
|
||||
seekbarTappingFingerprint.let {
|
||||
seekbarTappingMethod.let {
|
||||
val insertIndex = it.instructionMatches.last().index + 1
|
||||
|
||||
it.method.apply {
|
||||
val thisInstanceRegister = getInstruction<FiveRegisterInstruction>(
|
||||
insertIndex - 1
|
||||
insertIndex - 1,
|
||||
).registerC
|
||||
|
||||
val xAxisRegister = this.getInstruction<FiveRegisterInstruction>(
|
||||
it.instructionMatches[2].index
|
||||
it.instructionMatches[2].index,
|
||||
).registerD
|
||||
|
||||
val freeRegister = findFreeRegister(
|
||||
insertIndex, thisInstanceRegister, xAxisRegister
|
||||
insertIndex,
|
||||
thisInstanceRegister,
|
||||
xAxisRegister,
|
||||
)
|
||||
|
||||
val oMethod = seekbarTappingMethods[0]
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue