add suport YouTube v18.06.35

This commit is contained in:
inotia00
2023-02-18 14:18:23 +09:00
parent 9030abe616
commit 8427f28208
25 changed files with 315 additions and 194 deletions

View File

@ -0,0 +1,20 @@
package app.revanced.patches.youtube.layout.general.crowdfundingbox.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourcdIdPatch
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
object CrowdfundingBoxFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IPUT_OBJECT
),
customFingerprint = { methodDef ->
methodDef.implementation?.instructions?.any {
it.opcode.ordinal == Opcode.CONST.ordinal &&
(it as? WideLiteralInstruction)?.wideLiteral == SharedResourcdIdPatch.donationCompanionResourceId
} == true
}
)

View File

@ -1,90 +1,66 @@
package app.revanced.patches.youtube.layout.general.crowdfundingbox.patch
import app.revanced.extensions.findMutableMethodOf
import app.revanced.extensions.injectHideCall
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.annotation.YouTubeCompatibility
import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch
import app.revanced.patches.youtube.layout.general.crowdfundingbox.fingerprints.CrowdfundingBoxFingerprint
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourcdIdPatch
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.formats.Instruction22c
import org.jf.dexlib2.iface.instruction.formats.Instruction31i
import app.revanced.util.integrations.Constants.GENERAL_LAYOUT
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
@Patch
@Name("hide-crowdfunding-box")
@Description("Hides the crowdfunding box between the player and video description.")
@DependsOn(
[
ResourceMappingPatch::class,
SettingsPatch::class
SettingsPatch::class,
SharedResourcdIdPatch::class
]
)
@YouTubeCompatibility
@Version("0.0.1")
class CrowdfundingBoxPatch : BytecodePatch() {
// list of resource names to get the id of
private val resourceIds = arrayOf(
"donation_companion"
).map { name ->
ResourceMappingPatch.resourceMappings.single { it.name == name }.id
}
private var patchSuccessArray = Array(resourceIds.size) {false}
class CrowdfundingBoxPatch : BytecodePatch(
listOf(
CrowdfundingBoxFingerprint
)
) {
override fun execute(context: BytecodeContext): PatchResult {
context.classes.forEach { classDef ->
classDef.methods.forEach { method ->
with(method.implementation) {
this?.instructions?.forEachIndexed { index, instruction ->
when (instruction.opcode) {
Opcode.CONST -> {
when ((instruction as Instruction31i).wideLiteral) {
resourceIds[0] -> { // crowdfunding
val insertIndex = index + 3
val iPutInstruction = instructions.elementAt(insertIndex)
if (iPutInstruction.opcode != Opcode.IPUT_OBJECT) return@forEachIndexed
val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method)
CrowdfundingBoxFingerprint.result?.let {
with (it.mutableMethod) {
val insertIndex = it.scanResult.patternScanResult!!.endIndex
val register = (instruction(insertIndex) as TwoRegisterInstruction).registerA
val viewRegister = (iPutInstruction as Instruction22c).registerA
mutableMethod.implementation!!.injectHideCall(insertIndex, viewRegister, "layout/GeneralLayoutPatch", "hideCrowdfundingBox")
patchSuccessArray[0] = true;
}
}
}
else -> return@forEachIndexed
}
}
}
}
}
val errorIndex: Int = patchSuccessArray.indexOf(false)
if (errorIndex == -1) {
/*
* Add settings
*/
SettingsPatch.addPreference(
arrayOf(
"PREFERENCE: GENERAL_LAYOUT_SETTINGS",
"SETTINGS: HIDE_CROWDFUNDING_BOX"
addInstruction(
insertIndex,
"invoke-static {v$register}, $GENERAL_LAYOUT->hideCrowdfundingBox(Landroid/view/View;)V"
)
}
} ?: return CrowdfundingBoxFingerprint.toErrorResult()
/*
* Add settings
*/
SettingsPatch.addPreference(
arrayOf(
"PREFERENCE: GENERAL_LAYOUT_SETTINGS",
"SETTINGS: HIDE_CROWDFUNDING_BOX"
)
)
SettingsPatch.updatePatchStatus("hide-crowdfunding-box")
SettingsPatch.updatePatchStatus("hide-crowdfunding-box")
return PatchResultSuccess()
} else
return PatchResultError("Instruction not found: $errorIndex")
return PatchResultSuccess()
}
}

View File

@ -8,8 +8,8 @@ import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
object MiniPlayerDimensionsCalculatorFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "V",
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
customFingerprint = { methodDef ->
methodDef.implementation?.instructions?.any {
it.opcode.ordinal == Opcode.CONST.ordinal &&

View File

@ -9,5 +9,5 @@ object MiniPlayerOverrideFingerprint : MethodFingerprint(
returnType = "Z",
access = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("L"),
opcodes = listOf(Opcode.RETURN), // anchor to insert the instruction
opcodes = listOf(Opcode.INVOKE_STATIC), // anchor to insert the instruction
)

View File

@ -0,0 +1,12 @@
package app.revanced.patches.youtube.layout.general.tabletminiplayer.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
object MiniPlayerOverrideParentFingerprint : MethodFingerprint(
returnType = "L",
access = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("L"),
strings = listOf("VIDEO_QUALITIES_QUICK_MENU_BOTTOM_SHEET_FRAGMENT")
)

View File

@ -5,6 +5,7 @@ import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.data.toMethodWalker
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
@ -19,6 +20,7 @@ import app.revanced.patches.youtube.layout.general.tabletminiplayer.fingerprints
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourcdIdPatch
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
import app.revanced.util.integrations.Constants.GENERAL_LAYOUT
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@Patch
@ -35,31 +37,33 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
class TabletMiniPlayerPatch : BytecodePatch(
listOf(
MiniPlayerDimensionsCalculatorFingerprint,
MiniPlayerResponseModelSizeCheckFingerprint
MiniPlayerResponseModelSizeCheckFingerprint,
MiniPlayerOverrideParentFingerprint
)
) {
override fun execute(context: BytecodeContext): PatchResult {
MiniPlayerDimensionsCalculatorFingerprint.result?.let { parentResult ->
// first resolve the fingerprints via the parent fingerprint
val miniPlayerClass = parentResult.classDef
arrayOf(
MiniPlayerOverrideNoContextFingerprint,
MiniPlayerOverrideFingerprint,
MiniPlayerResponseModelSizeCheckFingerprint
).map {
it to (it.also { it.resolve(context, miniPlayerClass) }.result ?: return it.toErrorResult())
}.forEach { (fingerprint, result) ->
if (fingerprint == MiniPlayerOverrideNoContextFingerprint) {
val (method, _, parameterRegister) = result.addProxyCall()
method.insertOverride(method.implementation!!.instructions.size - 1, parameterRegister)
} else {
val (_, _, _) = result.addProxyCall()
}
}
MiniPlayerOverrideNoContextFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { result ->
val (method, _, parameterRegister) = result.addProxyCall()
method.insertOverride(method.implementation!!.instructions.size - 1, parameterRegister)
} ?: return MiniPlayerOverrideNoContextFingerprint.toErrorResult()
} ?: return MiniPlayerDimensionsCalculatorFingerprint.toErrorResult()
MiniPlayerOverrideParentFingerprint.result?.let { parentResult ->
MiniPlayerOverrideFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { result ->
(context.toMethodWalker(result.method)
.nextMethod(result.scanResult.patternScanResult!!.startIndex, true)
.getMethod() as MutableMethod)
.instructionProxyCall()
} ?: return MiniPlayerOverrideFingerprint.toErrorResult()
} ?: return MiniPlayerOverrideParentFingerprint.toErrorResult()
MiniPlayerResponseModelSizeCheckFingerprint.result?.let {
val (_, _, _) = it.addProxyCall()
} ?: return MiniPlayerResponseModelSizeCheckFingerprint.toErrorResult()
/*
* Add settings
*/
@ -94,6 +98,17 @@ class TabletMiniPlayerPatch : BytecodePatch(
)
}
fun MutableMethod.instructionProxyCall() {
val insertInstructions = this.implementation!!.instructions
for ((index, instruction) in insertInstructions.withIndex()) {
if (instruction.opcode != Opcode.RETURN) continue
val parameterRegister = (instruction as OneRegisterInstruction).registerA
this.insertOverride(index, parameterRegister)
this.insertOverride(insertInstructions.size - 1, parameterRegister)
break;
}
}
fun MethodFingerprintResult.unwrap(): Triple<MutableMethod, Int, Int> {
val scanIndex = this.scanResult.patternScanResult!!.endIndex
val method = this.mutableMethod