mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-05-17 06:47:15 +02:00
fix(YouTube - Change live ring click action): Clicking on the timestamp in the comments opens the channel
This commit is contained in:
parent
78f1d962cd
commit
da770b32bf
@ -1,5 +1,9 @@
|
|||||||
package app.revanced.extension.youtube.patches.general;
|
package app.revanced.extension.youtube.patches.general;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import app.revanced.extension.shared.utils.Logger;
|
import app.revanced.extension.shared.utils.Logger;
|
||||||
import app.revanced.extension.youtube.patches.general.requests.VideoDetailsRequest;
|
import app.revanced.extension.youtube.patches.general.requests.VideoDetailsRequest;
|
||||||
import app.revanced.extension.youtube.settings.Settings;
|
import app.revanced.extension.youtube.settings.Settings;
|
||||||
@ -10,16 +14,16 @@ public final class OpenChannelOfLiveAvatarPatch {
|
|||||||
private static final boolean CHANGE_LIVE_RING_CLICK_ACTION =
|
private static final boolean CHANGE_LIVE_RING_CLICK_ACTION =
|
||||||
Settings.CHANGE_LIVE_RING_CLICK_ACTION.get();
|
Settings.CHANGE_LIVE_RING_CLICK_ACTION.get();
|
||||||
|
|
||||||
private static volatile String videoId = "";
|
private static final AtomicBoolean engagementPanelOpen = new AtomicBoolean(false);
|
||||||
private static volatile boolean isCommentsPanelOpen = false;
|
|
||||||
private static volatile boolean liveChannelAvatarClicked = false;
|
private static volatile boolean liveChannelAvatarClicked = false;
|
||||||
|
private static volatile String videoId = "";
|
||||||
|
|
||||||
public static void commentsPanelClosed() {
|
public static void showEngagementPanel(@Nullable Object object) {
|
||||||
isCommentsPanelOpen = false;
|
engagementPanelOpen.set(object != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void commentsPanelOpen() {
|
public static void hideEngagementPanel() {
|
||||||
isCommentsPanelOpen = true;
|
engagementPanelOpen.compareAndSet(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void liveChannelAvatarClicked() {
|
public static void liveChannelAvatarClicked() {
|
||||||
@ -34,13 +38,14 @@ public final class OpenChannelOfLiveAvatarPatch {
|
|||||||
if (!liveChannelAvatarClicked) {
|
if (!liveChannelAvatarClicked) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (isCommentsPanelOpen) {
|
if (engagementPanelOpen.get()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
VideoDetailsRequest request = VideoDetailsRequest.getRequestForVideoId(videoId);
|
VideoDetailsRequest request = VideoDetailsRequest.getRequestForVideoId(videoId);
|
||||||
if (request != null) {
|
if (request != null) {
|
||||||
String channelId = request.getInfo();
|
String channelId = request.getInfo();
|
||||||
if (channelId != null) {
|
if (channelId != null) {
|
||||||
|
videoId = "";
|
||||||
liveChannelAvatarClicked = false;
|
liveChannelAvatarClicked = false;
|
||||||
VideoUtils.openChannel(channelId);
|
VideoUtils.openChannel(channelId);
|
||||||
return true;
|
return true;
|
||||||
@ -60,7 +65,7 @@ public final class OpenChannelOfLiveAvatarPatch {
|
|||||||
if (!liveChannelAvatarClicked) {
|
if (!liveChannelAvatarClicked) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isCommentsPanelOpen) {
|
if (engagementPanelOpen.get()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (newlyLoadedVideoId.isEmpty()) {
|
if (newlyLoadedVideoId.isEmpty()) {
|
||||||
|
@ -7,14 +7,14 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith
|
|||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patcher.patch.PatchException
|
import app.revanced.patcher.patch.PatchException
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
|
||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
import app.revanced.patcher.util.smali.ExternalLabel
|
||||||
import app.revanced.patches.shared.litho.addLithoFilter
|
import app.revanced.patches.shared.litho.addLithoFilter
|
||||||
import app.revanced.patches.shared.litho.emptyComponentLabel
|
import app.revanced.patches.shared.litho.emptyComponentLabel
|
||||||
import app.revanced.patches.shared.mainactivity.onCreateMethod
|
import app.revanced.patches.shared.mainactivity.onCreateMethod
|
||||||
import app.revanced.patches.youtube.utils.bottomsheet.bottomSheetHookPatch
|
import app.revanced.patches.youtube.utils.bottomsheet.bottomSheetHookPatch
|
||||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||||
import app.revanced.patches.youtube.utils.engagementPanelBuilderFingerprint
|
import app.revanced.patches.youtube.utils.engagement.engagementPanelHookPatch
|
||||||
|
import app.revanced.patches.youtube.utils.engagement.hookEngagementPanelState
|
||||||
import app.revanced.patches.youtube.utils.extension.Constants.COMPONENTS_PATH
|
import app.revanced.patches.youtube.utils.extension.Constants.COMPONENTS_PATH
|
||||||
import app.revanced.patches.youtube.utils.extension.Constants.FEED_CLASS_DESCRIPTOR
|
import app.revanced.patches.youtube.utils.extension.Constants.FEED_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.youtube.utils.extension.Constants.FEED_PATH
|
import app.revanced.patches.youtube.utils.extension.Constants.FEED_PATH
|
||||||
@ -41,19 +41,16 @@ import app.revanced.util.fingerprint.methodOrThrow
|
|||||||
import app.revanced.util.fingerprint.mutableClassOrThrow
|
import app.revanced.util.fingerprint.mutableClassOrThrow
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.getWalkerMethod
|
import app.revanced.util.getWalkerMethod
|
||||||
import app.revanced.util.indexOfFirstInstruction
|
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||||
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.Method
|
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.StringReference
|
import com.android.tools.smali.dexlib2.iface.reference.StringReference
|
||||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
|
||||||
|
|
||||||
private const val CAROUSEL_SHELF_FILTER_CLASS_DESCRIPTOR =
|
private const val CAROUSEL_SHELF_FILTER_CLASS_DESCRIPTOR =
|
||||||
"$COMPONENTS_PATH/CarouselShelfFilter;"
|
"$COMPONENTS_PATH/CarouselShelfFilter;"
|
||||||
@ -82,6 +79,7 @@ val feedComponentsPatch = bytecodePatch(
|
|||||||
sharedResourceIdPatch,
|
sharedResourceIdPatch,
|
||||||
settingsPatch,
|
settingsPatch,
|
||||||
bottomSheetHookPatch,
|
bottomSheetHookPatch,
|
||||||
|
engagementPanelHookPatch,
|
||||||
versionCheckPatch,
|
versionCheckPatch,
|
||||||
)
|
)
|
||||||
execute {
|
execute {
|
||||||
@ -176,38 +174,6 @@ val feedComponentsPatch = bytecodePatch(
|
|||||||
|
|
||||||
// region patch for hide relative video
|
// region patch for hide relative video
|
||||||
|
|
||||||
fun Method.indexOfEngagementPanelBuilderInstruction(targetMethod: MutableMethod) =
|
|
||||||
indexOfFirstInstruction {
|
|
||||||
opcode == Opcode.INVOKE_DIRECT &&
|
|
||||||
MethodUtil.methodSignaturesMatch(
|
|
||||||
targetMethod,
|
|
||||||
getReference<MethodReference>()!!
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
engagementPanelBuilderFingerprint.matchOrThrow().let {
|
|
||||||
it.classDef.methods.filter { method ->
|
|
||||||
method.indexOfEngagementPanelBuilderInstruction(it.method) >= 0
|
|
||||||
}.forEach { method ->
|
|
||||||
method.apply {
|
|
||||||
val index = indexOfEngagementPanelBuilderInstruction(it.method)
|
|
||||||
val register = getInstruction<OneRegisterInstruction>(index + 1).registerA
|
|
||||||
|
|
||||||
addInstruction(
|
|
||||||
index + 2,
|
|
||||||
"invoke-static {v$register}, " +
|
|
||||||
"$RELATED_VIDEO_CLASS_DESCRIPTOR->showEngagementPanel(Ljava/lang/Object;)V"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
engagementPanelUpdateFingerprint.methodOrThrow(engagementPanelBuilderFingerprint)
|
|
||||||
.addInstruction(
|
|
||||||
0,
|
|
||||||
"invoke-static {}, $RELATED_VIDEO_CLASS_DESCRIPTOR->hideEngagementPanel()V"
|
|
||||||
)
|
|
||||||
|
|
||||||
linearLayoutManagerItemCountsFingerprint.matchOrThrow().let {
|
linearLayoutManagerItemCountsFingerprint.matchOrThrow().let {
|
||||||
val methodWalker =
|
val methodWalker =
|
||||||
it.getWalkerMethod(it.patternMatch!!.endIndex)
|
it.getWalkerMethod(it.patternMatch!!.endIndex)
|
||||||
@ -224,6 +190,8 @@ val feedComponentsPatch = bytecodePatch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hookEngagementPanelState(RELATED_VIDEO_CLASS_DESCRIPTOR)
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region patch for hide subscriptions channel section for tablet
|
// region patch for hide subscriptions channel section for tablet
|
||||||
|
@ -11,12 +11,9 @@ import app.revanced.patches.youtube.utils.resourceid.filterBarHeight
|
|||||||
import app.revanced.patches.youtube.utils.resourceid.horizontalCardList
|
import app.revanced.patches.youtube.utils.resourceid.horizontalCardList
|
||||||
import app.revanced.patches.youtube.utils.resourceid.relatedChipCloudMargin
|
import app.revanced.patches.youtube.utils.resourceid.relatedChipCloudMargin
|
||||||
import app.revanced.util.fingerprint.legacyFingerprint
|
import app.revanced.util.fingerprint.legacyFingerprint
|
||||||
import app.revanced.util.getReference
|
|
||||||
import app.revanced.util.indexOfFirstInstruction
|
|
||||||
import app.revanced.util.or
|
import app.revanced.util.or
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
|
||||||
|
|
||||||
internal val breakingNewsFingerprint = legacyFingerprint(
|
internal val breakingNewsFingerprint = legacyFingerprint(
|
||||||
name = "breakingNewsFingerprint",
|
name = "breakingNewsFingerprint",
|
||||||
@ -103,19 +100,6 @@ internal val elementParserParentFingerprint = legacyFingerprint(
|
|||||||
strings = listOf("Element tree missing id in debug mode.")
|
strings = listOf("Element tree missing id in debug mode.")
|
||||||
)
|
)
|
||||||
|
|
||||||
internal val engagementPanelUpdateFingerprint = legacyFingerprint(
|
|
||||||
name = "engagementPanelUpdateFingerprint",
|
|
||||||
returnType = "V",
|
|
||||||
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
|
|
||||||
parameters = listOf("L", "Z"),
|
|
||||||
customFingerprint = { method, _ ->
|
|
||||||
method.indexOfFirstInstruction {
|
|
||||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
|
||||||
getReference<MethodReference>().toString() == "Ljava/util/ArrayDeque;->pop()Ljava/lang/Object;"
|
|
||||||
} >= 0
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
internal val filterBarHeightFingerprint = legacyFingerprint(
|
internal val filterBarHeightFingerprint = legacyFingerprint(
|
||||||
name = "filterBarHeightFingerprint",
|
name = "filterBarHeightFingerprint",
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
|
@ -40,39 +40,3 @@ internal fun indexOfPlaybackStartDescriptorInstruction(method: Method) =
|
|||||||
reference?.returnType == "Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;" &&
|
reference?.returnType == "Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;" &&
|
||||||
reference.parameterTypes.isEmpty()
|
reference.parameterTypes.isEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val engagementPanelCommentsClosedFingerprint = legacyFingerprint(
|
|
||||||
name = "engagementPanelCommentsClosedFingerprint",
|
|
||||||
returnType = "V",
|
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
|
||||||
parameters = emptyList(),
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.IGET_OBJECT,
|
|
||||||
Opcode.INVOKE_STATIC,
|
|
||||||
Opcode.IGET_OBJECT,
|
|
||||||
Opcode.INVOKE_DIRECT,
|
|
||||||
),
|
|
||||||
customFingerprint = { method, _ ->
|
|
||||||
method.indexOfFirstInstruction {
|
|
||||||
opcode == Opcode.INVOKE_INTERFACE &&
|
|
||||||
getReference<MethodReference>()?.name == "hasNext"
|
|
||||||
} >= 0
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
internal val engagementPanelCommentsOpenFingerprint = legacyFingerprint(
|
|
||||||
name = "engagementPanelCommentsOpenFingerprint",
|
|
||||||
returnType = "V",
|
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
|
||||||
parameters = listOf("L"),
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.IGET_OBJECT,
|
|
||||||
Opcode.IF_NE,
|
|
||||||
Opcode.RETURN_VOID,
|
|
||||||
Opcode.IPUT_OBJECT,
|
|
||||||
Opcode.RETURN_VOID,
|
|
||||||
),
|
|
||||||
customFingerprint = { method, _ ->
|
|
||||||
method.implementation!!.instructions.count() == 5
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
@ -6,7 +6,8 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith
|
|||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||||
import app.revanced.patches.youtube.utils.engagementPanelTitleParentFingerprint
|
import app.revanced.patches.youtube.utils.engagement.engagementPanelHookPatch
|
||||||
|
import app.revanced.patches.youtube.utils.engagement.hookEngagementPanelState
|
||||||
import app.revanced.patches.youtube.utils.extension.Constants.GENERAL_PATH
|
import app.revanced.patches.youtube.utils.extension.Constants.GENERAL_PATH
|
||||||
import app.revanced.patches.youtube.utils.patch.PatchList.CHANGE_LIVE_RING_CLICK_ACTION
|
import app.revanced.patches.youtube.utils.patch.PatchList.CHANGE_LIVE_RING_CLICK_ACTION
|
||||||
import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch
|
import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch
|
||||||
@ -31,30 +32,21 @@ val openChannelOfLiveAvatarPatch = bytecodePatch(
|
|||||||
compatibleWith(COMPATIBLE_PACKAGE)
|
compatibleWith(COMPATIBLE_PACKAGE)
|
||||||
|
|
||||||
dependsOn(
|
dependsOn(
|
||||||
playbackStartDescriptorPatch,
|
|
||||||
sharedResourceIdPatch,
|
|
||||||
settingsPatch,
|
settingsPatch,
|
||||||
|
sharedResourceIdPatch,
|
||||||
|
playbackStartDescriptorPatch,
|
||||||
|
engagementPanelHookPatch,
|
||||||
)
|
)
|
||||||
|
|
||||||
execute {
|
execute {
|
||||||
|
|
||||||
mapOf(
|
|
||||||
engagementPanelCommentsClosedFingerprint to "commentsPanelClosed",
|
|
||||||
engagementPanelCommentsOpenFingerprint to "commentsPanelOpen",
|
|
||||||
).forEach { (fingerprint, methodName) ->
|
|
||||||
fingerprint
|
|
||||||
.methodOrThrow(engagementPanelTitleParentFingerprint)
|
|
||||||
.addInstruction(
|
|
||||||
0,
|
|
||||||
"invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->$methodName()V"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
elementsImageFingerprint.methodOrThrow().addInstruction(
|
elementsImageFingerprint.methodOrThrow().addInstruction(
|
||||||
0,
|
0,
|
||||||
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->liveChannelAvatarClicked()V"
|
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->liveChannelAvatarClicked()V"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
hookEngagementPanelState(EXTENSION_CLASS_DESCRIPTOR)
|
||||||
|
|
||||||
clientSettingEndpointFingerprint.methodOrThrow().apply {
|
clientSettingEndpointFingerprint.methodOrThrow().apply {
|
||||||
val eqzIndex = indexOfFirstInstructionReversedOrThrow(Opcode.IF_EQZ)
|
val eqzIndex = indexOfFirstInstructionReversedOrThrow(Opcode.IF_EQZ)
|
||||||
var freeIndex = indexOfFirstInstructionReversedOrThrow(eqzIndex, Opcode.NEW_INSTANCE)
|
var freeIndex = indexOfFirstInstructionReversedOrThrow(eqzIndex, Opcode.NEW_INSTANCE)
|
||||||
|
@ -9,7 +9,6 @@ import app.revanced.patcher.util.smali.ExternalLabel
|
|||||||
import app.revanced.patches.shared.litho.addLithoFilter
|
import app.revanced.patches.shared.litho.addLithoFilter
|
||||||
import app.revanced.patches.shared.litho.lithoFilterPatch
|
import app.revanced.patches.shared.litho.lithoFilterPatch
|
||||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||||
import app.revanced.patches.youtube.utils.engagementPanelTitleParentFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.extension.Constants.COMPONENTS_PATH
|
import app.revanced.patches.youtube.utils.extension.Constants.COMPONENTS_PATH
|
||||||
import app.revanced.patches.youtube.utils.extension.Constants.PLAYER_CLASS_DESCRIPTOR
|
import app.revanced.patches.youtube.utils.extension.Constants.PLAYER_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.youtube.utils.patch.PatchList.DESCRIPTION_COMPONENTS
|
import app.revanced.patches.youtube.utils.patch.PatchList.DESCRIPTION_COMPONENTS
|
||||||
|
@ -16,6 +16,11 @@ internal val engagementPanelTitleFingerprint = legacyFingerprint(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
internal val engagementPanelTitleParentFingerprint = legacyFingerprint(
|
||||||
|
name = "engagementPanelTitleParentFingerprint",
|
||||||
|
strings = listOf("[EngagementPanelTitleHeader] Cannot remove action buttons from header as the child count is out of sync. Buttons to remove exceed current header child count.")
|
||||||
|
)
|
||||||
|
|
||||||
internal fun indexOfContentDescriptionInstruction(method: Method) =
|
internal fun indexOfContentDescriptionInstruction(method: Method) =
|
||||||
method.indexOfFirstInstructionReversed {
|
method.indexOfFirstInstructionReversed {
|
||||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||||
|
@ -59,11 +59,6 @@ internal val engagementPanelBuilderFingerprint = legacyFingerprint(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
internal val engagementPanelTitleParentFingerprint = legacyFingerprint(
|
|
||||||
name = "engagementPanelTitleParentFingerprint",
|
|
||||||
strings = listOf("[EngagementPanelTitleHeader] Cannot remove action buttons from header as the child count is out of sync. Buttons to remove exceed current header child count.")
|
|
||||||
)
|
|
||||||
|
|
||||||
internal val layoutConstructorFingerprint = legacyFingerprint(
|
internal val layoutConstructorFingerprint = legacyFingerprint(
|
||||||
name = "layoutConstructorFingerprint",
|
name = "layoutConstructorFingerprint",
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
package app.revanced.patches.youtube.utils.engagement
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
|
import app.revanced.patches.youtube.utils.engagementPanelBuilderFingerprint
|
||||||
|
import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch
|
||||||
|
import app.revanced.util.fingerprint.matchOrThrow
|
||||||
|
import app.revanced.util.fingerprint.methodOrThrow
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import app.revanced.util.indexOfFirstInstructionReversed
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.Method
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
|
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||||
|
|
||||||
|
private lateinit var hideEngagementPanelMethod: MutableMethod
|
||||||
|
private var showEngagementPanelMethods = mutableListOf<MutableMethod>()
|
||||||
|
|
||||||
|
val engagementPanelHookPatch = bytecodePatch(
|
||||||
|
description = "engagementPanelHookPatch"
|
||||||
|
) {
|
||||||
|
dependsOn(sharedResourceIdPatch)
|
||||||
|
|
||||||
|
execute {
|
||||||
|
engagementPanelBuilderFingerprint.matchOrThrow().let {
|
||||||
|
it.classDef.methods.filter { method ->
|
||||||
|
method.indexOfEngagementPanelBuilderInstruction(it.method) >= 0
|
||||||
|
}.forEach { method ->
|
||||||
|
showEngagementPanelMethods.add(method)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hideEngagementPanelMethod =
|
||||||
|
engagementPanelUpdateFingerprint.methodOrThrow(engagementPanelBuilderFingerprint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Method.indexOfEngagementPanelBuilderInstruction(targetMethod: MutableMethod) =
|
||||||
|
indexOfFirstInstructionReversed {
|
||||||
|
opcode == Opcode.INVOKE_DIRECT &&
|
||||||
|
MethodUtil.methodSignaturesMatch(
|
||||||
|
targetMethod,
|
||||||
|
getReference<MethodReference>()!!
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun hookEngagementPanelState(classDescriptor: String) {
|
||||||
|
showEngagementPanelMethods.forEach { method ->
|
||||||
|
method.apply {
|
||||||
|
val index = indexOfEngagementPanelBuilderInstruction(this)
|
||||||
|
val register = getInstruction<OneRegisterInstruction>(index + 1).registerA
|
||||||
|
|
||||||
|
addInstruction(
|
||||||
|
index + 2,
|
||||||
|
"invoke-static {v$register}, $classDescriptor->showEngagementPanel(Ljava/lang/Object;)V"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hideEngagementPanelMethod.addInstruction(
|
||||||
|
0,
|
||||||
|
"invoke-static {}, $classDescriptor->hideEngagementPanel()V"
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package app.revanced.patches.youtube.utils.engagement
|
||||||
|
|
||||||
|
import app.revanced.util.fingerprint.legacyFingerprint
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import app.revanced.util.indexOfFirstInstruction
|
||||||
|
import app.revanced.util.or
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
|
|
||||||
|
internal val engagementPanelUpdateFingerprint = legacyFingerprint(
|
||||||
|
name = "engagementPanelUpdateFingerprint",
|
||||||
|
returnType = "V",
|
||||||
|
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
|
||||||
|
parameters = listOf("L", "Z"),
|
||||||
|
customFingerprint = { method, _ ->
|
||||||
|
method.indexOfFirstInstruction {
|
||||||
|
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||||
|
getReference<MethodReference>().toString() == "Ljava/util/ArrayDeque;->pop()Ljava/lang/Object;"
|
||||||
|
} >= 0
|
||||||
|
}
|
||||||
|
)
|
Loading…
x
Reference in New Issue
Block a user