fix(youtube/theme): apply custom seekbar color to video thumbnails (#2085)

This commit is contained in:
LisoUseInAIKyrios
2023-05-11 10:22:37 +04:00
committed by GitHub
parent aa493c4f67
commit f891aa937c
13 changed files with 233 additions and 133 deletions
@@ -1,25 +0,0 @@
package app.revanced.patches.youtube.layout.theme.bytecode.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.theme.bytecode.fingerprints.CreateDarkThemeSeekbarFingerprint.indexOfInstructionWithSeekbarId
import app.revanced.patches.youtube.layout.theme.resource.ThemeResourcePatch
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.Method
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
object CreateDarkThemeSeekbarFingerprint : MethodFingerprint(
access = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
customFingerprint = { method -> method.indexOfInstructionWithSeekbarId != -1 },
) {
/**
* The index of the instruction that loads the resource id of the seekbar.
*/
internal val Method.indexOfInstructionWithSeekbarId
get() = implementation?.let {
it.instructions.indexOfFirst { instruction ->
instruction.opcode == Opcode.CONST && (instruction as WideLiteralInstruction).wideLiteral == ThemeResourcePatch.inlineTimeBarColorizedBarPlayedColorDarkId
}
}
}
@@ -1,4 +1,4 @@
package app.revanced.patches.youtube.layout.theme.fingerprints
package app.revanced.patches.youtube.layout.theme.bytecode.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
@@ -1,9 +0,0 @@
package app.revanced.patches.youtube.layout.theme.bytecode.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode
object SetSeekbarClickedColorFingerprint : MethodFingerprint(
opcodes = listOf(Opcode.CONST_HIGH16),
strings = listOf("YOUTUBE", "PREROLL", "POSTROLL")
)
@@ -0,0 +1,47 @@
package app.revanced.patches.youtube.layout.theme.bytecode.patch
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.addInstructions
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.youtube.layout.theme.annotations.ThemeCompatibility
import app.revanced.patches.youtube.layout.theme.bytecode.fingerprints.LithoThemeFingerprint
@Name("litho-color-hook")
@Description("Adds a hook to set color of Litho components.")
@ThemeCompatibility
@Version("0.0.1")
class LithoColorHookPatch : BytecodePatch(listOf(LithoThemeFingerprint)) {
override fun execute(context: BytecodeContext): PatchResult {
LithoThemeFingerprint.result?.let {
insertionIndex = it.scanResult.patternScanResult!!.endIndex - 1
colorRegister = "p1"
insertionMethod = it.mutableMethod
} ?: return LithoThemeFingerprint.toErrorResult()
return PatchResultSuccess()
}
companion object {
private var insertionIndex : Int = -1
private lateinit var colorRegister : String
private lateinit var insertionMethod : MutableMethod
internal fun lithoColorOverrideHook(targetMethodClass: String, targetMethodName: String) {
insertionMethod.addInstructions(
insertionIndex,
"""
invoke-static {$colorRegister}, $targetMethodClass->$targetMethodName(I)I
move-result $colorRegister
"""
)
insertionIndex += 2
}
}
}
@@ -1,76 +1,34 @@
package app.revanced.patches.youtube.layout.theme.bytecode.patch
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.data.toMethodWalker
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.layout.theme.annotations.ThemeCompatibility
import app.revanced.patches.youtube.layout.theme.bytecode.fingerprints.CreateDarkThemeSeekbarFingerprint
import app.revanced.patches.youtube.layout.theme.bytecode.fingerprints.CreateDarkThemeSeekbarFingerprint.indexOfInstructionWithSeekbarId
import app.revanced.patches.youtube.layout.theme.bytecode.fingerprints.SetSeekbarClickedColorFingerprint
import app.revanced.patches.youtube.layout.seekbar.bytecode.patch.SeekbarColorBytecodePatch
import app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints.CreateDarkThemeSeekbarFingerprint
import app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints.SetSeekbarClickedColorFingerprint
import app.revanced.patches.youtube.layout.theme.resource.ThemeResourcePatch
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
@Patch
@Name("theme")
@Description("Applies a custom theme.")
@DependsOn([ThemeLithoComponentsPatch::class, ThemeResourcePatch::class, IntegrationsPatch::class])
@ThemeCompatibility
@DependsOn([LithoColorHookPatch::class, SeekbarColorBytecodePatch::class, ThemeResourcePatch::class])
@Version("0.0.1")
class ThemeBytecodePatch : BytecodePatch(
listOf(CreateDarkThemeSeekbarFingerprint, SetSeekbarClickedColorFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
CreateDarkThemeSeekbarFingerprint.result?.let {
val putColorValueIndex = it.method.indexOfInstructionWithSeekbarId!! + 3
LithoColorHookPatch.lithoColorOverrideHook(INTEGRATIONS_CLASS_DESCRIPTOR, "getValue")
it.mutableMethod.apply {
val overrideRegister = instruction<TwoRegisterInstruction>(putColorValueIndex).registerA
addInstructions(
putColorValueIndex,
"""
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarColorValue()I
move-result v$overrideRegister
"""
)
}
} ?: return CreateDarkThemeSeekbarFingerprint.toErrorResult()
SetSeekbarClickedColorFingerprint.result?.let { result ->
result.mutableMethod.let {
val setColorMethodIndex = result.scanResult.patternScanResult!!.startIndex + 1
val method = context
.toMethodWalker(it)
.nextMethod(setColorMethodIndex, true)
.getMethod() as MutableMethod
method.apply {
val colorRegister = method.instruction<TwoRegisterInstruction>(0).registerA
addInstructions(
0,
"""
invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarClickedColorValue(I)I
move-result v$colorRegister
"""
)
}
}
} ?: return SetSeekbarClickedColorFingerprint.toErrorResult()
return PatchResultSuccess()
}
companion object : OptionsContainer() {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/theme/ThemePatch;"
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/theme/ThemeLithoComponentsPatch;"
var darkThemeBackgroundColor: String? by option(
PatchOption.StringOption(
@@ -1,40 +0,0 @@
package app.revanced.patches.youtube.layout.theme.bytecode.patch
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.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patches.youtube.layout.theme.annotations.ThemeCompatibility
import app.revanced.patches.youtube.layout.theme.fingerprints.LithoThemeFingerprint
@Name("theme-litho-components")
@Description("Applies a custom theme to Litho components.")
@ThemeCompatibility
@Version("0.0.1")
class ThemeLithoComponentsPatch : BytecodePatch(listOf(LithoThemeFingerprint)) {
override fun execute(context: BytecodeContext): PatchResult {
LithoThemeFingerprint.result?.let {
it.mutableMethod.apply {
val patchIndex = it.scanResult.patternScanResult!!.endIndex - 1
addInstructions(
patchIndex,
"""
invoke-static {p1}, $INTEGRATIONS_CLASS_DESCRIPTOR->getValue(I)I
move-result p1
"""
)
}
} ?: return LithoThemeFingerprint.toErrorResult()
return PatchResultSuccess()
}
private companion object {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/theme/ThemeLithoComponentsPatch;"
}
}
@@ -1,10 +1,7 @@
package app.revanced.patches.youtube.layout.theme.resource
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.InputType
@@ -28,19 +25,11 @@ class ThemeResourcePatch : ResourcePatch {
"#FF0000",
StringResource(
"revanced_seekbar_color_summary",
"The color of the seekbar for the dark theme."
"The color of the seekbar"
)
),
)
// Edit theme colors via bytecode.
// For that the resource id is used in a bytecode patch to change the color.
inlineTimeBarColorizedBarPlayedColorDarkId = ResourceMappingPatch.resourceMappings
.find { it.name == "inline_time_bar_colorized_bar_played_color_dark" }?.id
?: return PatchResultError("Could not find seekbar resource")
val darkThemeBackgroundColor = darkThemeBackgroundColor!!
val lightThemeBackgroundColor = lightThemeBackgroundColor!!
@@ -72,7 +61,4 @@ class ThemeResourcePatch : ResourcePatch {
return PatchResultSuccess()
}
internal companion object {
var inlineTimeBarColorizedBarPlayedColorDarkId = -1L
}
}