11package app.revanced.patches.youtube.layout.seekbar
22
33import app.revanced.patcher.Fingerprint
4- import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
54import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
65import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
76import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
8- import app.revanced.patcher.patch.PatchException
97import app.revanced.patcher.patch.bytecodePatch
108import app.revanced.patcher.patch.resourcePatch
119import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
@@ -17,17 +15,13 @@ import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
1715import app.revanced.patches.shared.misc.mapping.resourceMappings
1816import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
1917import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
20- import app.revanced.patches.youtube.misc.playservice.is_19_46_or_greater
2118import app.revanced.patches.youtube.misc.playservice.is_19_49_or_greater
2219import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
2320import app.revanced.patches.youtube.misc.settings.settingsPatch
2421import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
25- import app.revanced.util.copyXmlNode
26- import app.revanced.util.findElementByAttributeValueOrThrow
2722import app.revanced.util.findInstructionIndicesReversedOrThrow
2823import app.revanced.util.getReference
2924import app.revanced.util.indexOfFirstInstructionOrThrow
30- import app.revanced.util.inputStreamFromBundledResource
3125import app.revanced.util.insertLiteralOverride
3226import com.android.tools.smali.dexlib2.AccessFlags
3327import com.android.tools.smali.dexlib2.Opcode
@@ -38,9 +32,6 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
3832import com.android.tools.smali.dexlib2.iface.reference.MethodReference
3933import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
4034import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
41- import org.w3c.dom.Element
42- import java.io.ByteArrayInputStream
43- import kotlin.use
4435
4536internal var reelTimeBarPlayedColorId = - 1L
4637 private set
@@ -57,8 +48,6 @@ internal var ytTextSecondaryId = -1L
5748internal var inlineTimeBarLiveSeekableRangeId = - 1L
5849 private set
5950
60- internal const val splashSeekbarColorAttributeName = " splash_custom_seekbar_color"
61-
6251private val seekbarColorResourcePatch = resourcePatch {
6352 dependsOn(
6453 settingsPatch,
@@ -92,21 +81,6 @@ private val seekbarColorResourcePatch = resourcePatch {
9281 " inline_time_bar_live_seekable_range"
9382 ]
9483
95- // Modify the resume playback drawable and replace the progress bar with a custom drawable.
96- document(" res/drawable/resume_playback_progressbar_drawable.xml" ).use { document ->
97- val layerList = document.getElementsByTagName(" layer-list" ).item(0 ) as Element
98- val progressNode = layerList.getElementsByTagName(" item" ).item(1 ) as Element
99- if (! progressNode.getAttributeNode(" android:id" ).value.endsWith(" progress" )) {
100- throw PatchException (" Could not find progress bar" )
101- }
102- val scaleNode = progressNode.getElementsByTagName(" scale" ).item(0 ) as Element
103- val shapeNode = scaleNode.getElementsByTagName(" shape" ).item(0 ) as Element
104- val replacementNode = document.createElement(
105- " app.revanced.extension.youtube.patches.theme.ProgressBarDrawable" ,
106- )
107- scaleNode.replaceChild(replacementNode, shapeNode)
108- }
109-
11084 ytYoutubeMagentaColorId = resourceMappings[
11185 " color" ,
11286 " yt_youtube_magenta" ,
@@ -115,99 +89,9 @@ private val seekbarColorResourcePatch = resourcePatch {
11589 " attr" ,
11690 " ytStaticBrandRed" ,
11791 ]
118-
119- // Add attribute and styles for splash screen custom color.
120- // Using a style is the only way to selectively change just the seekbar fill color.
121- //
122- // Because the style colors must be hard coded for all color possibilities,
123- // instead of allowing 24 bit color the style is restricted to 9-bit (3 bits per color channel)
124- // and the style color closest to the users custom color is used for the splash screen.
125- arrayOf(
126- inputStreamFromBundledResource(" seekbar/values" , " attrs.xml" )!! to " res/values/attrs.xml" ,
127- ByteArrayInputStream (create9BitSeekbarColorStyles().toByteArray()) to " res/values/styles.xml"
128- ).forEach { (source, destination) ->
129- " resources" .copyXmlNode(
130- document(source),
131- document(destination),
132- ).close()
133- }
134-
135- fun setSplashDrawablePathFillColor (xmlFileNames : Iterable <String >, vararg resourceNames : String ) {
136- xmlFileNames.forEach { xmlFileName ->
137- document(xmlFileName).use { document ->
138- val childNodes = document.childNodes
139-
140- resourceNames.forEach { elementId ->
141- val element = childNodes.findElementByAttributeValueOrThrow(
142- " android:name" ,
143- elementId
144- )
145-
146- val attribute = " android:fillColor"
147- if (! element.hasAttribute(attribute)) {
148- throw PatchException (" Could not find $attribute for $elementId " )
149- }
150-
151- element.setAttribute(attribute, " ?attr/$splashSeekbarColorAttributeName " )
152- }
153- }
154- }
155- }
156-
157- setSplashDrawablePathFillColor(
158- listOf (
159- " res/drawable/\$ startup_animation_light__0.xml" ,
160- " res/drawable/\$ startup_animation_dark__0.xml"
161- ),
162- " _R_G_L_10_G_D_0_P_0"
163- )
164-
165- if (! is_19_46_or_greater) {
166- // Resources removed in 19.46+
167- setSplashDrawablePathFillColor(
168- listOf (
169- " res/drawable/\$ buenos_aires_animation_light__0.xml" ,
170- " res/drawable/\$ buenos_aires_animation_dark__0.xml"
171- ),
172- " _R_G_L_8_G_D_0_P_0"
173- )
174- }
17592 }
17693}
17794
178- /* *
179- * Generate a style xml with all combinations of 9-bit colors.
180- */
181- private fun create9BitSeekbarColorStyles (): String = StringBuilder ().apply {
182- append(" <?xml version=\" 1.0\" encoding=\" utf-8\" ?>" )
183- append(" <resources>\n " )
184-
185- for (red in 0 .. 7 ) {
186- for (green in 0 .. 7 ) {
187- for (blue in 0 .. 7 ) {
188- val name = " ${red} _${green} _${blue} "
189-
190- fun roundTo3BitHex (channel8Bits : Int ) =
191- (channel8Bits * 255 / 7 ).toString(16 ).padStart(2 , ' 0' )
192- val r = roundTo3BitHex(red)
193- val g = roundTo3BitHex(green)
194- val b = roundTo3BitHex(blue)
195- val color = " #ff$r$g$b "
196-
197- append(
198- """
199- <style name="splash_seekbar_color_style_$name ">
200- <item name="$splashSeekbarColorAttributeName ">$color </item>
201- </style>
202- """
203- )
204- }
205- }
206- }
207-
208- append(" </resources>" )
209- }.toString()
210-
21195private const val EXTENSION_CLASS_DESCRIPTOR = " Lapp/revanced/extension/youtube/patches/theme/SeekbarColorPatch;"
21296
21397val seekbarColorPatch = bytecodePatch(
@@ -344,21 +228,6 @@ val seekbarColorPatch = bytecodePatch(
344228
345229 // Hook the splash animation to set the a seekbar color.
346230 mainActivityOnCreateFingerprint.method.apply {
347- val drawableIndex = indexOfFirstInstructionOrThrow {
348- val reference = getReference<MethodReference >()
349- reference?.definingClass == " Landroid/widget/ImageView;"
350- && reference.name == " getDrawable"
351- }
352- val checkCastIndex = indexOfFirstInstructionOrThrow(drawableIndex, Opcode .CHECK_CAST )
353- val drawableRegister = getInstruction<OneRegisterInstruction >(checkCastIndex).registerA
354-
355- addInstruction(
356- checkCastIndex + 1 ,
357- " invoke-static { v$drawableRegister }, $EXTENSION_CLASS_DESCRIPTOR ->" +
358- " setSplashAnimationDrawableTheme(Landroid/graphics/drawable/AnimatedVectorDrawable;)V"
359- )
360-
361- // Replace the Lottie animation view setAnimation(int) call.
362231 val setAnimationIntMethodName = lottieAnimationViewSetAnimationIntFingerprint.originalMethod.name
363232
364233 findInstructionIndicesReversedOrThrow {
@@ -371,13 +240,11 @@ val seekbarColorPatch = bytecodePatch(
371240 replaceInstruction(
372241 index,
373242 " invoke-static { v${instruction.registerC} , v${instruction.registerD} }, " +
374- " $EXTENSION_CLASS_DESCRIPTOR ->setSplashAnimationLottie" +
375- " (Lcom/airbnb/lottie/LottieAnimationView;I)V"
243+ " $EXTENSION_CLASS_DESCRIPTOR ->setSplashAnimationLottie(Lcom/airbnb/lottie/LottieAnimationView;I)V"
376244 )
377245 }
378246 }
379247
380-
381248 // Add non obfuscated method aliases for `setAnimation(int)`
382249 // and `setAnimation(InputStream, String)` so extension code can call them.
383250 lottieAnimationViewSetAnimationIntFingerprint.classDef.methods.apply {
0 commit comments