feat(kakaotalk): add methods to handle deleted and hidden message layouts in ChatInfoView

This is the fifth commit to make deleted, hidden messages visible.
This commit is contained in:
2025-05-28 02:17:06 +09:00
parent 11bf82640d
commit d4e127ccf2
2 changed files with 113 additions and 3 deletions

View File

@ -6,14 +6,18 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.instructions
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.util.getReference
import app.revanced.patches.kakaotalk.chatlog.fingerprints.chatInfoViewConstructorFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction35c
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.immutable.ImmutableField
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodImplementation
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
import com.android.tools.smali.dexlib2.immutable.value.ImmutableBooleanEncodedValue
import com.google.common.collect.ImmutableList
val addDeletedOrHiddenLayoutPatch = bytecodePatch(
name = "Add deleted or hidden layout",
@ -31,9 +35,12 @@ val addDeletedOrHiddenLayoutPatch = bytecodePatch(
val onDrawMethod = chatInfoViewClass.methods.firstOrNull {
it.name == "onDraw"
} ?: error("onDraw method not found in ChatInfoView class")
val constructor = chatInfoViewConstructorFingerprint.method
println("ChatInfoView class: $chatInfoViewClass")
println("makeLayout method: $makeLayoutMethod")
println("onDraw method: $onDrawMethod")
println("constructor: $constructor")
chatInfoViewClass.apply {
fields.add(
@ -180,6 +187,64 @@ val addDeletedOrHiddenLayoutPatch = bytecodePatch(
).toMutable()
)
methods.add(
ImmutableMethod(
type,
"setDeleted",
ImmutableList.of(
ImmutableMethodParameter(
"Z",
null,
null
)
),
"V",
AccessFlags.PUBLIC.value or AccessFlags.FINAL.value,
null,
null,
MutableMethodImplementation(2)
).toMutable().apply {
addInstructions(
0,
"""
iput-boolean p1, p0, Lcom/kakao/talk/widget/chatlog/ChatInfoView;->isDeleted:Z
invoke-virtual {p0}, Landroid/view/View;->requestLayout()V
invoke-virtual {p0}, Landroid/view/View;->invalidate()V
return-void
""".trimIndent()
)
},
)
methods.add(
ImmutableMethod(
type,
"setHidden",
ImmutableList.of(
ImmutableMethodParameter(
"Z",
null,
null
)
),
"V",
AccessFlags.PUBLIC.value or AccessFlags.FINAL.value,
null,
null,
MutableMethodImplementation(2)
).toMutable().apply {
addInstructions(
0,
"""
iput-boolean p1, p0, Lcom/kakao/talk/widget/chatlog/ChatInfoView;->isHidden:Z
invoke-virtual {p0}, Landroid/view/View;->requestLayout()V
invoke-virtual {p0}, Landroid/view/View;->invalidate()V
return-void
""".trimIndent()
)
},
)
val cls = chatInfoViewClass.type
val deletedMakeLayoutBlock = """
@ -335,6 +400,39 @@ val addDeletedOrHiddenLayoutPatch = bytecodePatch(
deletedOnDrawBlock,
skipDeletedLabel
)
val indices = constructor.instructions
.withIndex()
.filter { it.value.opcode == Opcode.MOVE_RESULT_OBJECT }
.map { it.index }
val secondIndex = indices.getOrNull(1) ?: error("Second MOVE_RESULT_OBJECT instruction not found in constructor")
constructor.addInstructions(
secondIndex + 1,
"""
const/4 v0, 0x1
new-instance p3, Landroid/text/TextPaint;
invoke-direct {p3, v0}, Landroid/text/TextPaint;-><init>(I)V
iget v1, p0, $cls->deletedTextSize:I
int-to-float v1, v1
invoke-virtual {p3, v1}, Landroid/graphics/Paint;->setTextSize(F)V
iget v1, p0, $cls->deletedTextColor:I
invoke-virtual {p3, v1}, Landroid/graphics/Paint;->setColor(I)V
invoke-virtual {p3, p2}, Landroid/graphics/Paint;->setTypeface(Landroid/graphics/Typeface;)Landroid/graphics/Typeface;
iput-object p3, p0, $cls->deletedPaint:Landroid/text/TextPaint;
new-instance p3, Landroid/text/TextPaint;
invoke-direct {p3, v0}, Landroid/text/TextPaint;-><init>(I)V
iget v1, p0, $cls->hiddenTextSize:I
int-to-float v1, v1
invoke-virtual {p3, v1}, Landroid/graphics/Paint;->setTextSize(F)V
iget v1, p0, $cls->hiddenTextColor:I
invoke-virtual {p3, v1}, Landroid/graphics/Paint;->setColor(I)V
invoke-virtual {p3, p2}, Landroid/graphics/Paint;->setTypeface(Landroid/graphics/Typeface;)Landroid/graphics/Typeface;
iput-object p3, p0, $cls->hiddenPaint:Landroid/text/TextPaint;
""".trimIndent())
}
}
}

View File

@ -1,2 +1,14 @@
package app.revanced.patches.kakaotalk.chatlog.fingerprints
import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal val chatInfoViewConstructorFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
returns("V")
parameters("Landroid/content/Context;", "Landroid/util/AttributeSet;", "I")
strings(
"context"
)
custom { method, classDef -> classDef.type == "Lcom/kakao/talk/widget/chatlog/ChatInfoView;" && method.name == "<init>" }
}