mirror of
https://github.com/revanced/revanced-patches
synced 2024-11-10 12:29:23 +01:00
feat(twitter): hide-views-stats
patch (#1371)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
parent
36666f8c47
commit
2f04a06e3b
@ -0,0 +1,9 @@
|
|||||||
|
package app.revanced.patches.twitter.layout.hideviews.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility([Package("com.twitter.android")])
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class HideViewsCompatibility
|
@ -0,0 +1,15 @@
|
|||||||
|
package app.revanced.patches.twitter.layout.hideviews.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
object InlineActionTypesFingerprint : MethodFingerprint(
|
||||||
|
returnType = "Ljava/util/List",
|
||||||
|
access = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||||
|
strings = listOf(
|
||||||
|
"getCurrentMemoizing()",
|
||||||
|
"android_animated_reply_icon_enabled",
|
||||||
|
"reply_voting_android_position_before_favorite_enabled"
|
||||||
|
)
|
||||||
|
)
|
@ -0,0 +1,22 @@
|
|||||||
|
package app.revanced.patches.twitter.layout.hideviews.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
object TweetStatsContainerConstructorFingerprint : MethodFingerprint(
|
||||||
|
access = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||||
|
parameters = listOf("L"),
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.CONST,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.INVOKE_VIRTUAL
|
||||||
|
)
|
||||||
|
)
|
@ -0,0 +1,22 @@
|
|||||||
|
package app.revanced.patches.twitter.layout.hideviews.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
object TweetStatsContainerWrapperConstructorFingerprint : MethodFingerprint(
|
||||||
|
access = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||||
|
parameters = listOf("L"),
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.NEW_INSTANCE,
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT
|
||||||
|
)
|
||||||
|
)
|
@ -0,0 +1,26 @@
|
|||||||
|
package app.revanced.patches.twitter.layout.hideviews.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
object TweetStatsViewDelegateBinderFingerprint : MethodFingerprint(
|
||||||
|
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.NEW_INSTANCE,
|
||||||
|
Opcode.CONST_16,
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.NEW_INSTANCE,
|
||||||
|
Opcode.CONST_16,
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.RETURN_OBJECT
|
||||||
|
)
|
||||||
|
)
|
@ -0,0 +1,114 @@
|
|||||||
|
package app.revanced.patches.twitter.layout.hideviews.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.removeInstruction
|
||||||
|
import app.revanced.patcher.extensions.removeInstructions
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.PatchResult
|
||||||
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
|
import app.revanced.patches.twitter.layout.hideviews.fingerprints.InlineActionTypesFingerprint
|
||||||
|
import app.revanced.patches.twitter.layout.hideviews.fingerprints.TweetStatsContainerConstructorFingerprint
|
||||||
|
import app.revanced.patches.twitter.layout.hideviews.fingerprints.TweetStatsContainerWrapperConstructorFingerprint
|
||||||
|
import app.revanced.patches.twitter.layout.hideviews.fingerprints.TweetStatsViewDelegateBinderFingerprint
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
class HideViewsBytecodePatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
InlineActionTypesFingerprint,
|
||||||
|
TweetStatsContainerWrapperConstructorFingerprint,
|
||||||
|
TweetStatsContainerConstructorFingerprint,
|
||||||
|
TweetStatsViewDelegateBinderFingerprint
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
|
removeViewsFromTimeline(context)
|
||||||
|
removeTweetStatViewInitializer(context)
|
||||||
|
removeTweetStatViewWrapperInitializer(context)
|
||||||
|
removeViewDelegateBinderSubscription()
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeViewsFromTimeline(context: BytecodeContext) {
|
||||||
|
val addViewsToActionBarMethodFingerprint = object : MethodFingerprint(
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
)
|
||||||
|
) {}
|
||||||
|
transformMethodAtPattern(
|
||||||
|
context,
|
||||||
|
InlineActionTypesFingerprint,
|
||||||
|
addViewsToActionBarMethodFingerprint
|
||||||
|
) { patternScanResult, method ->
|
||||||
|
method.removeInstruction(patternScanResult.endIndex - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeTweetStatViewInitializer(context: BytecodeContext) {
|
||||||
|
val returnFingerprint = object : MethodFingerprint(
|
||||||
|
opcodes = listOf(Opcode.RETURN_VOID)
|
||||||
|
) {}
|
||||||
|
transformMethodAtPattern(
|
||||||
|
context,
|
||||||
|
TweetStatsContainerConstructorFingerprint,
|
||||||
|
returnFingerprint
|
||||||
|
) { patternScanResult, method ->
|
||||||
|
method.removeInstructions(patternScanResult.endIndex - 3, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeTweetStatViewWrapperInitializer(context: BytecodeContext) {
|
||||||
|
val wrapperReturnFingerprint = object : MethodFingerprint(
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.RETURN_VOID,
|
||||||
|
)
|
||||||
|
) {}
|
||||||
|
transformMethodAtPattern(
|
||||||
|
context,
|
||||||
|
TweetStatsContainerWrapperConstructorFingerprint,
|
||||||
|
wrapperReturnFingerprint
|
||||||
|
) { patternScanResult, method ->
|
||||||
|
method.removeInstructions(patternScanResult.startIndex - 4, 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeViewDelegateBinderSubscription() {
|
||||||
|
transformMethod(TweetStatsViewDelegateBinderFingerprint) { result, method ->
|
||||||
|
method.removeInstructions(result.scanResult.patternScanResult!!.startIndex - 4, 9)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun transformMethodAtPattern(
|
||||||
|
context: BytecodeContext, methodFingerprint: MethodFingerprint,
|
||||||
|
patternFingerprint: MethodFingerprint, transformer: TransformerAtPattern
|
||||||
|
) {
|
||||||
|
transformMethod(methodFingerprint) { result, method ->
|
||||||
|
val patternResult = patternFingerprint.also {
|
||||||
|
it.resolve(context, method, result.classDef)
|
||||||
|
}.result!!
|
||||||
|
transformer(patternResult.scanResult.patternScanResult!!, method)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun transformMethod(methodFingerprint: MethodFingerprint, transformer: Transformer) {
|
||||||
|
val result = methodFingerprint.result!!
|
||||||
|
val method = result.mutableMethod
|
||||||
|
transformer(result, method)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private typealias Transformer = (MethodFingerprintResult, MutableMethod) -> Unit
|
||||||
|
|
||||||
|
private typealias TransformerAtPattern = (MethodFingerprintResult.MethodFingerprintScanResult.PatternScanResult, MutableMethod) -> Unit
|
@ -0,0 +1,34 @@
|
|||||||
|
package app.revanced.patches.twitter.layout.hideviews.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.ResourceContext
|
||||||
|
import app.revanced.patcher.patch.*
|
||||||
|
import app.revanced.patcher.patch.annotations.DependsOn
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patches.twitter.layout.hideviews.annotations.HideViewsCompatibility
|
||||||
|
import org.w3c.dom.Element
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@DependsOn([HideViewsBytecodePatch::class])
|
||||||
|
@Name("hide-views-stats")
|
||||||
|
@Description("Hides the view stats under tweets.")
|
||||||
|
@HideViewsCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class HideViewsResourcePatch : ResourcePatch {
|
||||||
|
override fun execute(context: ResourceContext): PatchResult {
|
||||||
|
arrayOf(
|
||||||
|
"res/layout/condensed_tweet_stats.xml",
|
||||||
|
"res/layout/focal_tweet_stats.xml"
|
||||||
|
).forEach { file ->
|
||||||
|
context.xmlEditor[file].use { editor ->
|
||||||
|
val tags = editor.file.getElementsByTagName("com.twitter.ui.tweet.TweetStatView")
|
||||||
|
List(tags.length) { tags.item(it) as Element }
|
||||||
|
.filter { it.getAttribute("android:id").contains("views_stat") }
|
||||||
|
.forEach { it.parentNode.removeChild(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user