mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-05-20 16:27:17 +02:00
refactor(YouTube/Settings): reorganize settings menu
This commit is contained in:
parent
3bb394643e
commit
e1fd3c8586
@ -11,8 +11,7 @@ object DebuggingPatch : BaseResourcePatch(
|
||||
name = "Enable debug logging",
|
||||
description = "Adds an option to enable debug logging.",
|
||||
dependencies = setOf(SettingsPatch::class),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
use = false
|
||||
compatiblePackages = COMPATIBLE_PACKAGE
|
||||
) {
|
||||
override fun execute(context: ResourceContext) {
|
||||
|
||||
|
@ -64,7 +64,7 @@ object PlaybackSpeedFlyoutPanelHookPatch : BytecodePatch(
|
||||
INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR
|
||||
)!!.mutableClass
|
||||
videoUtilsMutableClass.methods.single { method ->
|
||||
method.name == "showPlaybackSpeedFlyoutPanel"
|
||||
method.name == "showPlaybackSpeedFlyoutMenu"
|
||||
}.apply {
|
||||
// add playback rate bottom sheet class
|
||||
videoUtilsMutableClass.staticFields.add(
|
||||
|
@ -4,6 +4,23 @@ import app.revanced.patcher.data.ResourceContext
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
object StringsElementsUtils {
|
||||
|
||||
internal fun ResourceContext.removeStringsElements(
|
||||
replacements: Array<String>
|
||||
) {
|
||||
var languageList = emptyArray<String>()
|
||||
val resourceDirectory = this["res"]
|
||||
val dir = resourceDirectory.listFiles()
|
||||
for (file in dir!!) {
|
||||
val path = file.name
|
||||
if (path.startsWith("values")) {
|
||||
val targetXml = resourceDirectory.resolve(path).resolve("strings.xml")
|
||||
if (targetXml.exists()) languageList += path
|
||||
}
|
||||
}
|
||||
removeStringsElements(languageList, replacements)
|
||||
}
|
||||
|
||||
internal fun ResourceContext.removeStringsElements(
|
||||
paths: Array<String>,
|
||||
replacements: Array<String>
|
||||
|
@ -1,99 +0,0 @@
|
||||
package app.revanced.patches.youtube.ads.fullscreen
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.ads.fullscreen.fingerprints.InterstitialsContainerFingerprint
|
||||
import app.revanced.patches.youtube.ads.fullscreen.fingerprints.ShowDialogCommandFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.InterstitialsContainer
|
||||
import app.revanced.util.getWideLiteralInstructionIndex
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch(dependencies = [SharedResourceIdPatch::class])
|
||||
object FullscreenAdsPatch : BytecodePatch(
|
||||
setOf(
|
||||
InterstitialsContainerFingerprint,
|
||||
ShowDialogCommandFingerprint
|
||||
)
|
||||
) {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"$COMPONENTS_PATH/AdsFilter;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
/**
|
||||
* Hides fullscreen ads
|
||||
* Non-litho view, used in some old clients.
|
||||
*/
|
||||
InterstitialsContainerFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = getWideLiteralInstructionIndex(InterstitialsContainer) + 2
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
targetIndex + 1,
|
||||
"invoke-static {v$targetRegister}, $FILTER_CLASS_DESCRIPTOR->hideFullscreenAds(Landroid/view/View;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides fullscreen ads
|
||||
* Litho view, used in 'ShowDialogCommandOuterClass' in innertube
|
||||
*/
|
||||
ShowDialogCommandFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
// In this method, custom dialog is created and shown.
|
||||
// There were no issues despite adding “return-void” to the first index.
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static {}, $FILTER_CLASS_DESCRIPTOR->hideFullscreenAds()Z
|
||||
move-result v0
|
||||
if-eqz v0, :show
|
||||
return-void
|
||||
""", ExternalLabel("show", getInstruction(0))
|
||||
)
|
||||
|
||||
// If an issue occurs due to patching due to server-side changes in the future,
|
||||
// Find the instruction whose name is "show" in [MethodReference] and click the 'AlertDialog.BUTTON_POSITIVE' button.
|
||||
//
|
||||
// In this case, an instruction for 'getButton' must be added to smali, not in integrations
|
||||
// (This custom dialog cannot be cast to [AlertDialog] or [Dialog])
|
||||
//
|
||||
// See the comments below.
|
||||
|
||||
// val dialogIndex = getTargetIndexWithMethodReferenceName("show")
|
||||
// val dialogReference = getInstruction<ReferenceInstruction>(dialogIndex).reference
|
||||
// val dialogDefiningClass = (dialogReference as MethodReference).definingClass
|
||||
// val getButtonMethod = context.findClass(dialogDefiningClass)!!
|
||||
// .mutableClass.methods.first { method ->
|
||||
// method.parameters == listOf("I")
|
||||
// && method.returnType == "Landroid/widget/Button;"
|
||||
// }
|
||||
// val getButtonCall = dialogDefiningClass + "->" + getButtonMethod.name + "(I)Landroid/widget/Button;"
|
||||
// val dialogRegister = getInstruction<FiveRegisterInstruction>(dialogIndex).registerC
|
||||
// val freeIndex = getTargetIndex(dialogIndex, Opcode.IF_EQZ)
|
||||
// val freeRegister = getInstruction<OneRegisterInstruction>(freeIndex).registerA
|
||||
|
||||
// addInstructions(
|
||||
// dialogIndex + 1, """
|
||||
// # Get the 'AlertDialog.BUTTON_POSITIVE' from custom dialog
|
||||
// # Since this custom dialog cannot be cast to AlertDialog or Dialog,
|
||||
// # It should come from smali, not integrations.
|
||||
// const/4 v$freeRegister, -0x1
|
||||
// invoke-virtual {v$dialogRegister, $freeRegister}, $getButtonCall
|
||||
// move-result-object $freeRegister
|
||||
// invoke-static {$freeRegister}, $FULLSCREEN_ADS_CLASS_DESCRIPTOR->confirmDialog(Landroid/widget/Button;)V
|
||||
// """
|
||||
// )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,20 +1,107 @@
|
||||
package app.revanced.patches.youtube.ads.general
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.ads.general.fingerprints.CompactYpcOfferModuleViewFingerprint
|
||||
import app.revanced.patches.youtube.ads.general.fingerprints.InterstitialsContainerFingerprint
|
||||
import app.revanced.patches.youtube.ads.general.fingerprints.ShowDialogCommandFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.ADS_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.AdAttribution
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.InterstitialsContainer
|
||||
import app.revanced.util.findMutableMethodOf
|
||||
import app.revanced.util.getWideLiteralInstructionIndex
|
||||
import app.revanced.util.injectHideViewCall
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction31i
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||
|
||||
@Patch(dependencies = [SharedResourceIdPatch::class])
|
||||
object GeneralAdsBytecodePatch : BytecodePatch(emptySet()) {
|
||||
object GeneralAdsBytecodePatch : BytecodePatch(
|
||||
setOf(
|
||||
CompactYpcOfferModuleViewFingerprint,
|
||||
InterstitialsContainerFingerprint,
|
||||
ShowDialogCommandFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
// region patch for hide fullscreen ads
|
||||
|
||||
// non-litho view, used in some old clients.
|
||||
InterstitialsContainerFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = getWideLiteralInstructionIndex(InterstitialsContainer) + 2
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
targetIndex + 1,
|
||||
"invoke-static {v$targetRegister}, $ADS_CLASS_DESCRIPTOR->hideFullscreenAds(Landroid/view/View;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// litho view, used in 'ShowDialogCommandOuterClass' in innertube
|
||||
ShowDialogCommandFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
// In this method, custom dialog is created and shown.
|
||||
// There were no issues despite adding “return-void” to the first index.
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static {}, $ADS_CLASS_DESCRIPTOR->hideFullscreenAds()Z
|
||||
move-result v0
|
||||
if-eqz v0, :show
|
||||
return-void
|
||||
""", ExternalLabel("show", getInstruction(0))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for hide general ads
|
||||
|
||||
hideAdAttributionView(context)
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for hide get premium
|
||||
|
||||
CompactYpcOfferModuleViewFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val startIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val measuredWidthRegister =
|
||||
getInstruction<TwoRegisterInstruction>(startIndex).registerA
|
||||
val measuredHeightInstruction =
|
||||
getInstruction<TwoRegisterInstruction>(startIndex + 1)
|
||||
val measuredHeightRegister = measuredHeightInstruction.registerA
|
||||
val tempRegister = measuredHeightInstruction.registerB
|
||||
|
||||
addInstructionsWithLabels(
|
||||
startIndex + 2, """
|
||||
invoke-static {}, $ADS_CLASS_DESCRIPTOR->hideGetPremium()Z
|
||||
move-result v$tempRegister
|
||||
if-eqz v$tempRegister, :show
|
||||
const/4 v$measuredWidthRegister, 0x0
|
||||
const/4 v$measuredHeightRegister, 0x0
|
||||
""", ExternalLabel("show", getInstruction(startIndex + 2))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
}
|
||||
|
||||
private fun hideAdAttributionView(context: BytecodeContext) {
|
||||
context.classes.forEach { classDef ->
|
||||
classDef.methods.forEach { method ->
|
||||
method.implementation.apply {
|
||||
@ -40,7 +127,7 @@ object GeneralAdsBytecodePatch : BytecodePatch(emptySet()) {
|
||||
.injectHideViewCall(
|
||||
insertIndex,
|
||||
viewRegister,
|
||||
"$COMPONENTS_PATH/AdsFilter;",
|
||||
ADS_CLASS_DESCRIPTOR,
|
||||
"hideAdAttributionView"
|
||||
)
|
||||
}
|
||||
|
@ -2,14 +2,12 @@ package app.revanced.patches.youtube.ads.general
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patches.shared.litho.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.ads.fullscreen.FullscreenAdsPatch
|
||||
import app.revanced.patches.youtube.ads.getpremium.GetPremiumPatch
|
||||
import app.revanced.patches.youtube.ads.video.VideoAdsPatch
|
||||
import app.revanced.patches.youtube.utils.fix.doublebacktoclose.DoubleBackToClosePatch
|
||||
import app.revanced.patches.youtube.utils.fix.swiperefresh.SwipeRefreshPatch
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.copyXmlNode
|
||||
import app.revanced.util.doRecursively
|
||||
import app.revanced.util.patch.BaseResourcePatch
|
||||
import app.revanced.util.startsWithAny
|
||||
@ -17,16 +15,15 @@ import org.w3c.dom.Element
|
||||
|
||||
@Suppress("DEPRECATION", "unused")
|
||||
object GeneralAdsPatch : BaseResourcePatch(
|
||||
name = "Hide general ads",
|
||||
description = "Adds options to hide general ads.",
|
||||
name = "Hide ads",
|
||||
description = "Adds options to hide ads.",
|
||||
dependencies = setOf(
|
||||
DoubleBackToClosePatch::class,
|
||||
FullscreenAdsPatch::class,
|
||||
GeneralAdsBytecodePatch::class,
|
||||
GetPremiumPatch::class,
|
||||
LithoFilterPatch::class,
|
||||
SettingsPatch::class,
|
||||
SwipeRefreshPatch::class
|
||||
SwipeRefreshPatch::class,
|
||||
VideoAdsPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE
|
||||
) {
|
||||
@ -87,24 +84,15 @@ object GeneralAdsPatch : BaseResourcePatch(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy arrays
|
||||
*/
|
||||
context.copyXmlNode("youtube/doubleback/host", "values/arrays.xml", "resources")
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: ADS_SETTINGS",
|
||||
"SETTINGS: HIDE_GENERAL_ADS",
|
||||
|
||||
"SETTINGS: DOUBLE_BACK_TIMEOUT"
|
||||
"PREFERENCE_SCREEN: ADS"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide general ads")
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.ads.getpremium.fingerprints
|
||||
package app.revanced.patches.youtube.ads.general.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
@ -15,5 +15,8 @@ internal object CompactYpcOfferModuleViewFingerprint : MethodFingerprint(
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.RETURN_VOID
|
||||
),
|
||||
customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("/CompactYpcOfferModuleView;") && methodDef.name == "onMeasure" }
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.definingClass.endsWith("/CompactYpcOfferModuleView;")
|
||||
&& methodDef.name == "onMeasure"
|
||||
}
|
||||
)
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.ads.fullscreen.fingerprints
|
||||
package app.revanced.patches.youtube.ads.general.fingerprints
|
||||
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.InterstitialsContainer
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.ads.fullscreen.fingerprints
|
||||
package app.revanced.patches.youtube.ads.general.fingerprints
|
||||
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.SlidingDialogAnimation
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
@ -1,44 +0,0 @@
|
||||
package app.revanced.patches.youtube.ads.getpremium
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.ads.getpremium.fingerprints.CompactYpcOfferModuleViewFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
|
||||
object GetPremiumPatch : BytecodePatch(
|
||||
setOf(CompactYpcOfferModuleViewFingerprint)
|
||||
) {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"$COMPONENTS_PATH/AdsFilter;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
CompactYpcOfferModuleViewFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val startIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val measuredWidthRegister =
|
||||
getInstruction<TwoRegisterInstruction>(startIndex).registerA
|
||||
val measuredHeightInstruction =
|
||||
getInstruction<TwoRegisterInstruction>(startIndex + 1)
|
||||
val measuredHeightRegister = measuredHeightInstruction.registerA
|
||||
val tempRegister = measuredHeightInstruction.registerB
|
||||
|
||||
addInstructionsWithLabels(
|
||||
startIndex + 2, """
|
||||
invoke-static {}, $FILTER_CLASS_DESCRIPTOR->hideGetPremium()Z
|
||||
move-result v$tempRegister
|
||||
if-eqz v$tempRegister, :show
|
||||
const/4 v$measuredWidthRegister, 0x0
|
||||
const/4 v$measuredHeightRegister, 0x0
|
||||
""", ExternalLabel("show", getInstruction(startIndex + 2))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package app.revanced.patches.youtube.ads.video
|
||||
|
||||
import app.revanced.patches.shared.ads.BaseAdsPatch
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.ADS_PATH
|
||||
|
||||
object VideoAdsBytecodePatch : BaseAdsPatch(
|
||||
"$ADS_PATH/VideoAdsPatch;",
|
||||
"hideVideoAds"
|
||||
)
|
@ -1,33 +1,9 @@
|
||||
package app.revanced.patches.youtube.ads.video
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseResourcePatch
|
||||
import app.revanced.patches.shared.ads.BaseAdsPatch
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.ADS_CLASS_DESCRIPTOR
|
||||
|
||||
@Suppress("unused")
|
||||
object VideoAdsPatch : BaseResourcePatch(
|
||||
name = "Hide video ads",
|
||||
description = "Adds an option to hide ads in the video player.",
|
||||
dependencies = setOf(
|
||||
SettingsPatch::class,
|
||||
VideoAdsBytecodePatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE
|
||||
) {
|
||||
override fun execute(context: ResourceContext) {
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: ADS_SETTINGS",
|
||||
"SETTINGS: HIDE_VIDEO_ADS"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide video ads")
|
||||
|
||||
}
|
||||
}
|
||||
object VideoAdsPatch : BaseAdsPatch(
|
||||
ADS_CLASS_DESCRIPTOR,
|
||||
"hideVideoAds"
|
||||
)
|
||||
|
@ -16,8 +16,6 @@ import app.revanced.patches.youtube.alternativethumbnails.general.fingerprints.c
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.ALTERNATIVE_THUMBNAILS_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch.contexts
|
||||
import app.revanced.util.copyXmlNode
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
@ -149,20 +147,15 @@ object AlternativeThumbnailsPatch : BaseBytecodePatch(
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy arrays
|
||||
*/
|
||||
contexts.copyXmlNode("youtube/alternativethumbnails/host", "values/arrays.xml", "resources")
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: ALTERNATIVE_THUMBNAILS_SETTINGS"
|
||||
"PREFERENCE_SCREEN: ALTERNATIVE_THUMBNAILS"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Alternative thumbnails")
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
||||
|
@ -1,38 +0,0 @@
|
||||
package app.revanced.patches.youtube.buttomplayer.gestures
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patches.youtube.buttomplayer.gestures.fingerprints.BottomPlayerGesturesFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.BOTTOM_PLAYER_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.literalInstructionBooleanHook
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
|
||||
@Suppress("unused")
|
||||
object BottomPlayerGesturesPatch : BaseBytecodePatch(
|
||||
name = "Enable bottom player gestures",
|
||||
description = "Adds an option to enter fullscreen when swiping down below the video player.",
|
||||
dependencies = setOf(SettingsPatch::class),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(BottomPlayerGesturesFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
BottomPlayerGesturesFingerprint.literalInstructionBooleanHook(
|
||||
45372793,
|
||||
"$BOTTOM_PLAYER_CLASS_DESCRIPTOR->enableBottomPlayerGestures()Z"
|
||||
)
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: BOTTOM_PLAYER_SETTINGS",
|
||||
"SETTINGS: ENABLE_BOTTOM_PLAYER_GESTURES"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Enable bottom player gestures")
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
package app.revanced.patches.youtube.buttomplayer.gestures.fingerprints
|
||||
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||
|
||||
internal object BottomPlayerGesturesFingerprint : LiteralValueFingerprint(
|
||||
returnType = "V",
|
||||
literalSupplier = { 45372793 }
|
||||
)
|
@ -0,0 +1,229 @@
|
||||
package app.revanced.patches.youtube.feed.components
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.shared.litho.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.feed.components.fingerprints.BreakingNewsFingerprint
|
||||
import app.revanced.patches.youtube.feed.components.fingerprints.ChannelListSubMenuFingerprint
|
||||
import app.revanced.patches.youtube.feed.components.fingerprints.DefaultsTabsBarFingerprint
|
||||
import app.revanced.patches.youtube.feed.components.fingerprints.ElementParserFingerprint
|
||||
import app.revanced.patches.youtube.feed.components.fingerprints.ElementParserParentFingerprint
|
||||
import app.revanced.patches.youtube.feed.components.fingerprints.FilterBarHeightFingerprint
|
||||
import app.revanced.patches.youtube.feed.components.fingerprints.LatestVideosButtonFingerprint
|
||||
import app.revanced.patches.youtube.feed.components.fingerprints.RelatedChipCloudFingerprint
|
||||
import app.revanced.patches.youtube.feed.components.fingerprints.SearchResultsChipBarFingerprint
|
||||
import app.revanced.patches.youtube.feed.components.fingerprints.ShowMoreButtonFingerprint
|
||||
import app.revanced.patches.youtube.utils.browseid.BrowseIdHookPatch
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.FEED_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.navigation.NavigationBarHookPatch
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TabsBarTextTabView
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.getTargetIndex
|
||||
import app.revanced.util.getWideLiteralInstructionIndex
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
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.TwoRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
@Suppress("unused")
|
||||
object FeedComponentsPatch : BaseBytecodePatch(
|
||||
name = "Hide feed components",
|
||||
description = "Adds options to hide components related to feed.",
|
||||
dependencies = setOf(
|
||||
BrowseIdHookPatch::class,
|
||||
LithoFilterPatch::class,
|
||||
NavigationBarHookPatch::class,
|
||||
SettingsPatch::class,
|
||||
SharedResourceIdPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(
|
||||
BreakingNewsFingerprint,
|
||||
ChannelListSubMenuFingerprint,
|
||||
DefaultsTabsBarFingerprint,
|
||||
ElementParserParentFingerprint,
|
||||
FilterBarHeightFingerprint,
|
||||
LatestVideosButtonFingerprint,
|
||||
RelatedChipCloudFingerprint,
|
||||
SearchResultsChipBarFingerprint,
|
||||
ShowMoreButtonFingerprint
|
||||
)
|
||||
) {
|
||||
private const val FEED_COMPONENTS_FILTER_CLASS_DESCRIPTOR =
|
||||
"$COMPONENTS_PATH/FeedComponentsFilter;"
|
||||
private const val FEED_VIDEO_FILTER_CLASS_DESCRIPTOR =
|
||||
"$COMPONENTS_PATH/FeedVideoFilter;"
|
||||
private const val KEYWORD_FILTER_CLASS_DESCRIPTOR =
|
||||
"$COMPONENTS_PATH/KeywordContentFilter;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
// region patch for hide carousel shelf, subscriptions channel section, latest videos button
|
||||
|
||||
mapOf(
|
||||
BreakingNewsFingerprint to "hideBreakingNewsShelf", // carousel shelf, only used to tablet layout.
|
||||
ChannelListSubMenuFingerprint to "hideSubscriptionsChannelSection", // subscriptions channel section
|
||||
LatestVideosButtonFingerprint to "hideLatestVideosButton", // latest videos button
|
||||
).forEach { (fingerprint, methodName) ->
|
||||
fingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
targetIndex + 1,
|
||||
"invoke-static {v$targetRegister}, $FEED_CLASS_DESCRIPTOR->$methodName(Landroid/view/View;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for hide category bar
|
||||
|
||||
FilterBarHeightFingerprint.patch<TwoRegisterInstruction> { register ->
|
||||
"""
|
||||
invoke-static { v$register }, $FEED_CLASS_DESCRIPTOR->hideCategoryBarInFeed(I)I
|
||||
move-result v$register
|
||||
"""
|
||||
}
|
||||
|
||||
RelatedChipCloudFingerprint.patch<OneRegisterInstruction>(1) { register ->
|
||||
"invoke-static { v$register }, " +
|
||||
"$FEED_CLASS_DESCRIPTOR->hideCategoryBarInRelatedVideos(Landroid/view/View;)V"
|
||||
}
|
||||
|
||||
SearchResultsChipBarFingerprint.patch<OneRegisterInstruction>(-1, -2) { register ->
|
||||
"""
|
||||
invoke-static { v$register }, $FEED_CLASS_DESCRIPTOR->hideCategoryBarInSearch(I)I
|
||||
move-result v$register
|
||||
"""
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for hide channel profile
|
||||
|
||||
DefaultsTabsBarFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val viewIndex = getWideLiteralInstructionIndex(TabsBarTextTabView) + 2
|
||||
val viewRegister = getInstruction<OneRegisterInstruction>(viewIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
viewIndex + 1,
|
||||
"invoke-static {v$viewRegister}, $FEED_CLASS_DESCRIPTOR->setChannelTabView(Landroid/view/View;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for hide mix playlists
|
||||
|
||||
ElementParserFingerprint.resolve(
|
||||
context,
|
||||
ElementParserParentFingerprint.resultOrThrow().classDef
|
||||
)
|
||||
ElementParserFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val freeRegister = implementation!!.registerCount - parameters.size - 2
|
||||
val insertIndex = indexOfFirstInstruction {
|
||||
val reference = ((this as? ReferenceInstruction)?.reference as? MethodReference)
|
||||
|
||||
reference?.parameterTypes?.size == 1
|
||||
&& reference.parameterTypes.first() == "[B"
|
||||
&& reference.returnType.startsWith("L")
|
||||
}
|
||||
|
||||
val objectIndex = getTargetIndex(Opcode.MOVE_OBJECT)
|
||||
val objectRegister = getInstruction<TwoRegisterInstruction>(objectIndex).registerA
|
||||
|
||||
val jumpIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
|
||||
addInstructionsWithLabels(
|
||||
insertIndex, """
|
||||
invoke-static {v$objectRegister, v$freeRegister}, $FEED_COMPONENTS_FILTER_CLASS_DESCRIPTOR->filterMixPlaylists(Ljava/lang/Object;[B)Z
|
||||
move-result v$freeRegister
|
||||
if-nez v$freeRegister, :filter
|
||||
""", ExternalLabel("filter", getInstruction(jumpIndex))
|
||||
)
|
||||
|
||||
addInstruction(
|
||||
0,
|
||||
"move-object/from16 v$freeRegister, p3"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for hide show more button
|
||||
|
||||
ShowMoreButtonFingerprint.resultOrThrow().let {
|
||||
val getViewMethod =
|
||||
it.mutableClass.methods.find { method ->
|
||||
method.parameters.isEmpty() &&
|
||||
method.returnType == "Landroid/view/View;"
|
||||
}
|
||||
|
||||
getViewMethod?.apply {
|
||||
val targetIndex = implementation!!.instructions.size - 1
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
targetIndex,
|
||||
"invoke-static {v$targetRegister}, $FEED_CLASS_DESCRIPTOR->hideShowMoreButton(Landroid/view/View;)V"
|
||||
)
|
||||
} ?: throw PatchException("Failed to find getView method")
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
LithoFilterPatch.addFilter(FEED_COMPONENTS_FILTER_CLASS_DESCRIPTOR)
|
||||
LithoFilterPatch.addFilter(FEED_VIDEO_FILTER_CLASS_DESCRIPTOR)
|
||||
LithoFilterPatch.addFilter(KEYWORD_FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE_SCREEN: FEED",
|
||||
"SETTINGS: HIDE_FEED_COMPONENTS"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
|
||||
private fun <RegisterInstruction : OneRegisterInstruction> MethodFingerprint.patch(
|
||||
insertIndexOffset: Int = 0,
|
||||
hookRegisterOffset: Int = 0,
|
||||
instructions: (Int) -> String
|
||||
) =
|
||||
resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
|
||||
val insertIndex = endIndex + insertIndexOffset
|
||||
val register =
|
||||
getInstruction<RegisterInstruction>(endIndex + hookRegisterOffset).registerA
|
||||
|
||||
addInstructions(insertIndex, instructions(register))
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.general.suggestionshelf.fingerprints
|
||||
package app.revanced.patches.youtube.feed.components.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.HorizontalCardList
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.general.channellistsubmenu.fingerprints
|
||||
package app.revanced.patches.youtube.feed.components.fingerprints
|
||||
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ChannelListSubMenu
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.general.channelprofile.fingerprints
|
||||
package app.revanced.patches.youtube.feed.components.fingerprints
|
||||
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TabsBarTextTabView
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.general.mixplaylists.fingerprints
|
||||
package app.revanced.patches.youtube.feed.components.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.general.mixplaylists.fingerprints
|
||||
package app.revanced.patches.youtube.feed.components.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.general.categorybar.fingerprints
|
||||
package app.revanced.patches.youtube.feed.components.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.FilterBarHeight
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.general.latestvideosbutton.fingerprints
|
||||
package app.revanced.patches.youtube.feed.components.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.Bar
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.general.categorybar.fingerprints
|
||||
package app.revanced.patches.youtube.feed.components.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.RelatedChipCloudMargin
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.general.categorybar.fingerprints
|
||||
package app.revanced.patches.youtube.feed.components.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.BarContainerHeight
|
@ -1,10 +1,10 @@
|
||||
package app.revanced.patches.youtube.general.loadmorebutton.fingerprints
|
||||
package app.revanced.patches.youtube.feed.components.fingerprints
|
||||
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ExpandButtonDown
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object LoadMoreButtonFingerprint : LiteralValueFingerprint(
|
||||
internal object ShowMoreButtonFingerprint : LiteralValueFingerprint(
|
||||
opcodes = listOf(
|
||||
Opcode.CONST,
|
||||
Opcode.CONST_4,
|
@ -1,15 +1,15 @@
|
||||
package app.revanced.patches.youtube.flyoutpanel.feed
|
||||
package app.revanced.patches.youtube.feed.flyoutmenu
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patches.youtube.flyoutpanel.feed.fingerprints.BottomSheetMenuItemBuilderFingerprint
|
||||
import app.revanced.patches.youtube.flyoutpanel.feed.fingerprints.BottomSheetMenuItemBuilderLegacyFingerprint
|
||||
import app.revanced.patches.youtube.flyoutpanel.feed.fingerprints.ContextualMenuItemBuilderFingerprint
|
||||
import app.revanced.patches.youtube.feed.flyoutmenu.fingerprints.BottomSheetMenuItemBuilderFingerprint
|
||||
import app.revanced.patches.youtube.feed.flyoutmenu.fingerprints.BottomSheetMenuItemBuilderLegacyFingerprint
|
||||
import app.revanced.patches.youtube.feed.flyoutmenu.fingerprints.ContextualMenuItemBuilderFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.FLYOUT_PANEL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.FEED_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
@ -20,9 +20,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
@Suppress("unused")
|
||||
object FeedFlyoutPanelPatch : BaseBytecodePatch(
|
||||
name = "Hide feed flyout panel",
|
||||
description = "Adds the ability to hide feed flyout panel components using a custom filter.",
|
||||
object FeedFlyoutMenuPatch : BaseBytecodePatch(
|
||||
name = "Hide feed flyout menu",
|
||||
description = "Adds the ability to hide feed flyout menu components using a custom filter.",
|
||||
dependencies = setOf(
|
||||
SettingsPatch::class,
|
||||
SharedResourceIdPatch::class
|
||||
@ -54,7 +54,7 @@ object FeedFlyoutPanelPatch : BaseBytecodePatch(
|
||||
|
||||
addInstructions(
|
||||
targetIndex + 1, """
|
||||
invoke-static {v$targetRegister}, $FLYOUT_PANEL_CLASS_DESCRIPTOR->hideFeedFlyoutPanel(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
|
||||
invoke-static {v$targetRegister}, $FEED_CLASS_DESCRIPTOR->hideFlyoutMenu(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
|
||||
move-result-object v$targetRegister
|
||||
"""
|
||||
)
|
||||
@ -77,7 +77,7 @@ object FeedFlyoutPanelPatch : BaseBytecodePatch(
|
||||
addInstruction(
|
||||
targetIndex + 1,
|
||||
"invoke-static {v${targetInstruction.registerC}, v${targetInstruction.registerD}}, " +
|
||||
"$FLYOUT_PANEL_CLASS_DESCRIPTOR->hideFeedFlyoutPanel(Landroid/widget/TextView;Ljava/lang/CharSequence;)V"
|
||||
"$FEED_CLASS_DESCRIPTOR->hideFlyoutMenu(Landroid/widget/TextView;Ljava/lang/CharSequence;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -87,12 +87,11 @@ object FeedFlyoutPanelPatch : BaseBytecodePatch(
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: FLYOUT_PANEL_SETTINGS",
|
||||
"SETTINGS: HIDE_FEED_FLYOUT_PANEL"
|
||||
"PREFERENCE_SCREEN: FEED",
|
||||
"SETTINGS: HIDE_FEED_FLYOUT_MENU"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide feed flyout panel")
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.flyoutpanel.feed.fingerprints
|
||||
package app.revanced.patches.youtube.feed.flyoutmenu.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.flyoutpanel.feed.fingerprints
|
||||
package app.revanced.patches.youtube.feed.flyoutmenu.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.flyoutpanel.feed.fingerprints
|
||||
package app.revanced.patches.youtube.feed.flyoutmenu.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.PosterArtWidthDefault
|
@ -1,107 +0,0 @@
|
||||
package app.revanced.patches.youtube.flyoutpanel.oldqualitylayout
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.shared.litho.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.utils.fingerprints.QualityMenuViewInflateFingerprint
|
||||
import app.revanced.patches.youtube.utils.fingerprints.QualitySetterFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.FLYOUT_PANEL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.recyclerview.BottomSheetRecyclerViewPatch
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.getTargetIndex
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
@Suppress("unused")
|
||||
object OldQualityLayoutPatch : BaseBytecodePatch(
|
||||
name = "Enable old quality layout",
|
||||
description = "Adds an option to restore the old video quality menu with specific video resolution options.",
|
||||
dependencies = setOf(
|
||||
BottomSheetRecyclerViewPatch::class,
|
||||
LithoFilterPatch::class,
|
||||
SettingsPatch::class,
|
||||
SharedResourceIdPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(
|
||||
QualityMenuViewInflateFingerprint,
|
||||
QualitySetterFingerprint
|
||||
)
|
||||
) {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"$COMPONENTS_PATH/VideoQualityMenuFilter;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
/**
|
||||
* Non-litho view, used in old clients and Shorts.
|
||||
*/
|
||||
val videoQualityClass = QualitySetterFingerprint.resultOrThrow().mutableMethod.definingClass
|
||||
|
||||
QualityMenuViewInflateFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
insertIndex + 1,
|
||||
"invoke-static { v$insertRegister }, $FLYOUT_PANEL_CLASS_DESCRIPTOR->enableOldQualityMenu(Landroid/widget/ListView;)V"
|
||||
)
|
||||
}
|
||||
val onItemClickMethod =
|
||||
it.mutableClass.methods.find { method -> method.name == "onItemClick" }
|
||||
|
||||
onItemClickMethod?.apply {
|
||||
val insertIndex = getTargetIndex(Opcode.IGET_OBJECT)
|
||||
val insertRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
val jumpIndex = indexOfFirstInstruction {
|
||||
opcode == Opcode.IGET_OBJECT
|
||||
&& this.getReference<FieldReference>()?.type == videoQualityClass
|
||||
}
|
||||
|
||||
addInstructionsWithLabels(
|
||||
insertIndex, """
|
||||
invoke-static {}, $FLYOUT_PANEL_CLASS_DESCRIPTOR->enableOldQualityMenu()Z
|
||||
move-result v$insertRegister
|
||||
if-nez v$insertRegister, :show
|
||||
""", ExternalLabel("show", getInstruction(jumpIndex))
|
||||
)
|
||||
} ?: throw PatchException("Failed to find onItemClick method")
|
||||
}
|
||||
|
||||
/**
|
||||
* Litho view
|
||||
*/
|
||||
BottomSheetRecyclerViewPatch.injectCall("$FLYOUT_PANEL_CLASS_DESCRIPTOR->onFlyoutMenuCreate(Landroid/support/v7/widget/RecyclerView;)V")
|
||||
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: FLYOUT_PANEL_SETTINGS",
|
||||
"SETTINGS: PLAYER_FLYOUT_PANEL_HEADER",
|
||||
"SETTINGS: ENABLE_OLD_QUALITY_LAYOUT"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Enable old quality layout")
|
||||
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
package app.revanced.patches.youtube.fullscreen.autoplaypreview
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.utils.fingerprints.LayoutConstructorFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.FULLSCREEN_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.AutoNavPreviewStub
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.AutoNavToggle
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.getStringInstructionIndex
|
||||
import app.revanced.util.getWideLiteralInstructionIndex
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
object AutoplayPreviewPatch : BaseBytecodePatch(
|
||||
name = "Hide autoplay preview",
|
||||
description = "Adds an option to hide the autoplay preview container when in fullscreen.",
|
||||
dependencies = setOf(
|
||||
SettingsPatch::class,
|
||||
SharedResourceIdPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(LayoutConstructorFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
LayoutConstructorFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val dummyRegister =
|
||||
getInstruction<OneRegisterInstruction>(getStringInstructionIndex("1.0x")).registerA
|
||||
val insertIndex = getWideLiteralInstructionIndex(AutoNavPreviewStub)
|
||||
val jumpIndex = getWideLiteralInstructionIndex(AutoNavToggle) - 1
|
||||
|
||||
addInstructionsWithLabels(
|
||||
insertIndex, """
|
||||
invoke-static {}, $FULLSCREEN_CLASS_DESCRIPTOR->hideAutoPlayPreview()Z
|
||||
move-result v$dummyRegister
|
||||
if-nez v$dummyRegister, :hidden
|
||||
""", ExternalLabel("hidden", getInstruction(jumpIndex))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: FULLSCREEN_SETTINGS",
|
||||
"SETTINGS: HIDE_AUTOPLAY_PREVIEW"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide autoplay preview")
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,59 +0,0 @@
|
||||
package app.revanced.patches.youtube.fullscreen.compactcontrolsoverlay
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patches.youtube.utils.fingerprints.YouTubeControlsOverlayFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.FULLSCREEN_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.getWalkerMethod
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
object CompactControlsOverlayPatch : BaseBytecodePatch(
|
||||
name = "Enable compact controls overlay",
|
||||
description = "Adds an option to make the fullscreen controls compact.",
|
||||
dependencies = setOf(
|
||||
SettingsPatch::class,
|
||||
SharedResourceIdPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(YouTubeControlsOverlayFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
YouTubeControlsOverlayFingerprint.resultOrThrow().let {
|
||||
val walkerMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex)
|
||||
walkerMethod.apply {
|
||||
val insertIndex = implementation!!.instructions.size - 1
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static {v$targetRegister}, $FULLSCREEN_CLASS_DESCRIPTOR->enableCompactControlsOverlay(Z)Z
|
||||
move-result v$targetRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: FULLSCREEN_SETTINGS",
|
||||
"SETTINGS: FULLSCREEN_EXPERIMENTAL_FLAGS",
|
||||
"SETTINGS: ENABLE_COMPACT_CONTROLS_OVERLAY"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Enable compact controls overlay")
|
||||
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
package app.revanced.patches.youtube.fullscreen.endscreenoverlay
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.fullscreen.endscreenoverlay.fingerprints.EndScreenResultsParentFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.FULLSCREEN_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
|
||||
@Suppress("unused")
|
||||
object EndScreenOverlayPatch : BaseBytecodePatch(
|
||||
name = "Hide end screen overlay",
|
||||
description = "Adds an option to hide the overlay in fullscreen when swiping up and at the end of videos.",
|
||||
dependencies = setOf(
|
||||
SettingsPatch::class,
|
||||
SharedResourceIdPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(EndScreenResultsParentFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
EndScreenResultsParentFingerprint.resultOrThrow().let {
|
||||
it.mutableClass.methods.find { method -> method.parameters == listOf("I", "Z", "I") }
|
||||
?.apply {
|
||||
addInstructionsWithLabels(
|
||||
0, """
|
||||
invoke-static {}, $FULLSCREEN_CLASS_DESCRIPTOR->hideEndScreenOverlay()Z
|
||||
move-result v0
|
||||
if-eqz v0, :show
|
||||
return-void
|
||||
""", ExternalLabel("show", getInstruction(0))
|
||||
)
|
||||
} ?: throw PatchException("Could not find targetMethod")
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: FULLSCREEN_SETTINGS",
|
||||
"SETTINGS: HIDE_END_SCREEN_OVERLAY"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide end screen overlay")
|
||||
|
||||
}
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
package app.revanced.patches.youtube.fullscreen.forcefullscreen
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patches.youtube.fullscreen.forcefullscreen.fingerprints.ClientSettingEndpointFingerprint
|
||||
import app.revanced.patches.youtube.fullscreen.forcefullscreen.fingerprints.VideoPortraitParentFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.FULLSCREEN_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.getStringInstructionIndex
|
||||
import app.revanced.util.getTargetIndex
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
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.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
object ForceFullscreenPatch : BaseBytecodePatch(
|
||||
name = "Force fullscreen",
|
||||
description = "Adds an option to forcefully open videos in fullscreen.",
|
||||
dependencies = setOf(SettingsPatch::class),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(
|
||||
ClientSettingEndpointFingerprint,
|
||||
VideoPortraitParentFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
/**
|
||||
* Process that hooks Activity for using {Activity.setRequestedOrientation}.
|
||||
*/
|
||||
ClientSettingEndpointFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val getActivityIndex = getStringInstructionIndex("watch") + 2
|
||||
val getActivityReference =
|
||||
getInstruction<ReferenceInstruction>(getActivityIndex).reference
|
||||
val classRegister =
|
||||
getInstruction<TwoRegisterInstruction>(getActivityIndex).registerB
|
||||
|
||||
val watchDescriptorMethodIndex =
|
||||
getStringInstructionIndex("start_watch_minimized") - 1
|
||||
val watchDescriptorRegister =
|
||||
getInstruction<FiveRegisterInstruction>(watchDescriptorMethodIndex).registerD
|
||||
|
||||
addInstructions(
|
||||
watchDescriptorMethodIndex, """
|
||||
invoke-static {v$watchDescriptorRegister}, $FULLSCREEN_CLASS_DESCRIPTOR->forceFullscreen(Z)Z
|
||||
move-result v$watchDescriptorRegister
|
||||
"""
|
||||
)
|
||||
|
||||
val insertIndex = getStringInstructionIndex("force_fullscreen")
|
||||
val freeRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex, """
|
||||
iget-object v$freeRegister, v$classRegister, $getActivityReference
|
||||
check-cast v$freeRegister, Landroid/app/Activity;
|
||||
sput-object v$freeRegister, $FULLSCREEN_CLASS_DESCRIPTOR->watchDescriptorActivity:Landroid/app/Activity;
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't rotate the screen in vertical video.
|
||||
* Add an instruction to check the vertical video.
|
||||
*/
|
||||
VideoPortraitParentFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val stringIndex =
|
||||
getStringInstructionIndex("Acquiring NetLatencyActionLogger failed. taskId=")
|
||||
val invokeIndex = getTargetIndex(stringIndex, Opcode.INVOKE_INTERFACE)
|
||||
val targetIndex = getTargetIndex(invokeIndex, Opcode.CHECK_CAST)
|
||||
val targetClass = context
|
||||
.findClass(getInstruction<ReferenceInstruction>(targetIndex).reference.toString())!!
|
||||
.mutableClass
|
||||
|
||||
targetClass.methods.find { method -> method.parameters == listOf("I", "I", "Z") }
|
||||
?.apply {
|
||||
addInstruction(
|
||||
1,
|
||||
"invoke-static {p1, p2}, $FULLSCREEN_CLASS_DESCRIPTOR->setVideoPortrait(II)V"
|
||||
)
|
||||
} ?: throw PatchException("Could not find targetMethod")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: FULLSCREEN_SETTINGS",
|
||||
"SETTINGS: FULLSCREEN_EXPERIMENTAL_FLAGS",
|
||||
"SETTINGS: FORCE_FULLSCREEN"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Force fullscreen")
|
||||
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
package app.revanced.patches.youtube.fullscreen.fullscreenpanels
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.fullscreen.fullscreenpanels.fingerprints.FullscreenEngagementPanelFingerprint
|
||||
import app.revanced.patches.youtube.utils.fingerprints.LayoutConstructorFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.FULLSCREEN_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.quickactions.QuickActionsHookPatch
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.FullScreenEngagementPanel
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.getTargetIndex
|
||||
import app.revanced.util.getTargetIndexWithMethodReferenceName
|
||||
import app.revanced.util.getWideLiteralInstructionIndex
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
object FullscreenPanelsPatch : BaseBytecodePatch(
|
||||
name = "Hide fullscreen panels",
|
||||
description = "Adds an option to hide panels such as live chat when in fullscreen.",
|
||||
dependencies = setOf(
|
||||
QuickActionsHookPatch::class,
|
||||
SettingsPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(
|
||||
FullscreenEngagementPanelFingerprint,
|
||||
LayoutConstructorFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
FullscreenEngagementPanelFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val literalIndex = getWideLiteralInstructionIndex(FullScreenEngagementPanel)
|
||||
val targetIndex = getTargetIndex(literalIndex, Opcode.CHECK_CAST)
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
targetIndex + 1,
|
||||
"invoke-static {v$targetRegister}, $FULLSCREEN_CLASS_DESCRIPTOR->hideFullscreenPanels(Landroidx/coordinatorlayout/widget/CoordinatorLayout;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
LayoutConstructorFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val dummyIndex = getWideLiteralInstructionIndex(159962)
|
||||
val dummyRegister = getInstruction<OneRegisterInstruction>(dummyIndex).registerA
|
||||
val addViewIndex = getTargetIndexWithMethodReferenceName("addView")
|
||||
|
||||
addInstructionsWithLabels(
|
||||
addViewIndex, """
|
||||
invoke-static {}, $FULLSCREEN_CLASS_DESCRIPTOR->showFullscreenTitle()Z
|
||||
move-result v$dummyRegister
|
||||
if-eqz v$dummyRegister, :hidden
|
||||
""", ExternalLabel("hidden", getInstruction(addViewIndex + 1))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: FULLSCREEN_SETTINGS",
|
||||
"SETTINGS: HIDE_FULLSCREEN_PANELS"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide fullscreen panels")
|
||||
|
||||
}
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
package app.revanced.patches.youtube.fullscreen.landscapemode
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patches.youtube.fullscreen.landscapemode.fingerprints.BroadcastReceiverFingerprint
|
||||
import app.revanced.patches.youtube.fullscreen.landscapemode.fingerprints.LandScapeModeConfigFingerprint
|
||||
import app.revanced.patches.youtube.fullscreen.landscapemode.fingerprints.OrientationParentFingerprint
|
||||
import app.revanced.patches.youtube.fullscreen.landscapemode.fingerprints.OrientationPrimaryFingerprint
|
||||
import app.revanced.patches.youtube.fullscreen.landscapemode.fingerprints.OrientationSecondaryFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.FULLSCREEN_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.getStringInstructionIndex
|
||||
import app.revanced.util.getTargetIndex
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
object LandScapeModePatch : BaseBytecodePatch(
|
||||
name = "Landscape mode",
|
||||
description = "Adds an option to disable landscape mode when entering fullscreen" +
|
||||
"and an option to keep landscape mode when turning the screen off and on in fullscreen.",
|
||||
dependencies = setOf(SettingsPatch::class),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(
|
||||
BroadcastReceiverFingerprint,
|
||||
LandScapeModeConfigFingerprint,
|
||||
OrientationParentFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
/**
|
||||
* Disable landscape mode
|
||||
*/
|
||||
OrientationParentFingerprint.resultOrThrow().classDef.let { classDef ->
|
||||
arrayOf(
|
||||
OrientationPrimaryFingerprint,
|
||||
OrientationSecondaryFingerprint
|
||||
).forEach { fingerprint ->
|
||||
fingerprint.resolve(context, classDef)
|
||||
|
||||
fingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val index = it.scanResult.patternScanResult!!.endIndex
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
addInstructions(
|
||||
index + 1, """
|
||||
invoke-static {v$register}, $FULLSCREEN_CLASS_DESCRIPTOR->disableLandScapeMode(Z)Z
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep landscape mode
|
||||
*/
|
||||
LandScapeModeConfigFingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = implementation!!.instructions.size - 1
|
||||
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex, """
|
||||
invoke-static {v$insertRegister}, $FULLSCREEN_CLASS_DESCRIPTOR->keepFullscreen(Z)Z
|
||||
move-result v$insertRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
BroadcastReceiverFingerprint.resultOrThrow().let { result ->
|
||||
result.mutableMethod.apply {
|
||||
val stringIndex = getStringInstructionIndex("android.intent.action.SCREEN_ON")
|
||||
val insertIndex = getTargetIndex(stringIndex, Opcode.IF_EQZ) + 1
|
||||
|
||||
addInstruction(
|
||||
insertIndex,
|
||||
"invoke-static {}, $FULLSCREEN_CLASS_DESCRIPTOR->setScreenStatus()V"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"SETTINGS: KEEP_LANDSCAPE_MODE"
|
||||
)
|
||||
)
|
||||
} // no exceptions are raised for compatibility with all versions.
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: FULLSCREEN_SETTINGS",
|
||||
"SETTINGS: FULLSCREEN_EXPERIMENTAL_FLAGS",
|
||||
"SETTINGS: DISABLE_LANDSCAPE_MODE"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Landscape mode")
|
||||
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
package app.revanced.patches.youtube.fullscreen.quickactions
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patches.shared.litho.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
|
||||
import app.revanced.patches.youtube.utils.quickactions.QuickActionsHookPatch
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
|
||||
@Suppress("unused")
|
||||
object QuickActionsComponentsPatch : BaseBytecodePatch(
|
||||
name = "Quick actions components",
|
||||
description = "Adds options to hide and customize components below the seekbar in fullscreen.",
|
||||
dependencies = setOf(
|
||||
LithoFilterPatch::class,
|
||||
QuickActionsHookPatch::class,
|
||||
SettingsPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE
|
||||
) {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"$COMPONENTS_PATH/QuickActionFilter;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
QuickActionsHookPatch.injectQuickActionMargin()
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: BOTTOM_PLAYER_SETTINGS",
|
||||
"SETTINGS: QUICK_ACTIONS_COMPONENTS"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Quick actions components")
|
||||
|
||||
}
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.accountmenu
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patches.youtube.general.accountmenu.fingerprints.AccountListFingerprint
|
||||
import app.revanced.patches.youtube.general.accountmenu.fingerprints.AccountListParentFingerprint
|
||||
import app.revanced.patches.youtube.general.accountmenu.fingerprints.AccountMenuFingerprint
|
||||
import app.revanced.patches.youtube.general.accountmenu.fingerprints.AccountMenuParentFingerprint
|
||||
import app.revanced.patches.youtube.general.accountmenu.fingerprints.AccountMenuPatchFingerprint
|
||||
import app.revanced.patches.youtube.general.accountmenu.fingerprints.SetViewGroupMarginFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
object AccountMenuPatch : BaseBytecodePatch(
|
||||
name = "Hide account menu",
|
||||
description = "Adds the ability to hide account menu elements using a custom filter in the account menu and You tab.",
|
||||
dependencies = setOf(
|
||||
SettingsPatch::class,
|
||||
SharedResourceIdPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(
|
||||
AccountListParentFingerprint,
|
||||
AccountMenuParentFingerprint,
|
||||
AccountMenuPatchFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
AccountListParentFingerprint.resultOrThrow().let { parentResult ->
|
||||
AccountListFingerprint.resolve(context, parentResult.classDef)
|
||||
|
||||
AccountListFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = it.scanResult.patternScanResult!!.startIndex + 3
|
||||
val targetInstruction = getInstruction<FiveRegisterInstruction>(targetIndex)
|
||||
|
||||
addInstruction(
|
||||
targetIndex,
|
||||
"invoke-static {v${targetInstruction.registerC}, v${targetInstruction.registerD}}, " +
|
||||
"$GENERAL_CLASS_DESCRIPTOR->hideAccountList(Landroid/view/View;Ljava/lang/CharSequence;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AccountMenuParentFingerprint.resultOrThrow().let { parentResult ->
|
||||
AccountMenuFingerprint.resolve(context, parentResult.classDef)
|
||||
SetViewGroupMarginFingerprint.resolve(context, parentResult.classDef)
|
||||
|
||||
AccountMenuFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = it.scanResult.patternScanResult!!.startIndex + 2
|
||||
val targetInstruction = getInstruction<FiveRegisterInstruction>(targetIndex)
|
||||
|
||||
addInstruction(
|
||||
targetIndex,
|
||||
"invoke-static {v${targetInstruction.registerC}, v${targetInstruction.registerD}}, " +
|
||||
"$GENERAL_CLASS_DESCRIPTOR->hideAccountMenu(Landroid/view/View;Ljava/lang/CharSequence;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
SetViewGroupMarginFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val setViewGroupMarginIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val setViewGroupMarginReference =
|
||||
getInstruction<ReferenceInstruction>(setViewGroupMarginIndex).reference
|
||||
|
||||
AccountMenuPatchFingerprint.resultOrThrow().mutableMethod.addInstructions(
|
||||
0, """
|
||||
const/4 v0, 0x0
|
||||
invoke-static {p0, v0, v0}, $setViewGroupMarginReference
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"SETTINGS: HIDE_ACCOUNT_MENU"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide account menu")
|
||||
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.accountmenu.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object AccountMenuPatchFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PRIVATE or AccessFlags.STATIC,
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.definingClass == GENERAL_CLASS_DESCRIPTOR
|
||||
&& methodDef.name == "hideAccountMenu"
|
||||
}
|
||||
)
|
@ -32,7 +32,6 @@ object AutoCaptionsPatch : BaseBytecodePatch(
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Disable auto captions")
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.autopopuppanels
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.general.autopopuppanels.fingerprints.EngagementPanelControllerFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
|
||||
@Suppress("unused")
|
||||
object PlayerPopupPanelsPatch : BaseBytecodePatch(
|
||||
name = "Hide auto player popup panels",
|
||||
description = "Adds an option to hide panels (such as live chat) from opening automatically.",
|
||||
dependencies = setOf(SettingsPatch::class),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(EngagementPanelControllerFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
EngagementPanelControllerFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
addInstructionsWithLabels(
|
||||
0, """
|
||||
invoke-static {}, $GENERAL_CLASS_DESCRIPTOR->hideAutoPlayerPopupPanels()Z
|
||||
move-result v0
|
||||
if-eqz v0, :shown
|
||||
# The type of the fourth parameter is boolean.
|
||||
if-eqz p4, :shown
|
||||
const/4 v0, 0x0
|
||||
return-object v0
|
||||
""", ExternalLabel("shown", getInstruction(0))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"SETTINGS: HIDE_AUTO_PLAYER_POPUP_PANELS"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide auto player popup panels")
|
||||
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.castbutton
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patches.youtube.general.castbutton.fingerprints.CastButtonFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
|
||||
@Suppress("unused")
|
||||
object CastButtonPatch : BaseBytecodePatch(
|
||||
name = "Hide cast button",
|
||||
description = "Adds an option to hide the cast button.",
|
||||
dependencies = setOf(SettingsPatch::class),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(CastButtonFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
CastButtonFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
addInstructions(
|
||||
0, """
|
||||
invoke-static {p1}, $GENERAL_CLASS_DESCRIPTOR->hideCastButton(I)I
|
||||
move-result p1
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"SETTINGS: HIDE_CAST_BUTTON"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide cast button")
|
||||
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.castbutton.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal object CastButtonFingerprint : MethodFingerprint(
|
||||
parameters = listOf("I"),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.definingClass.endsWith("/MediaRouteButton;")
|
||||
&& methodDef.name == "setVisibility"
|
||||
}
|
||||
)
|
@ -1,85 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.categorybar
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.general.categorybar.fingerprints.FilterBarHeightFingerprint
|
||||
import app.revanced.patches.youtube.general.categorybar.fingerprints.RelatedChipCloudFingerprint
|
||||
import app.revanced.patches.youtube.general.categorybar.fingerprints.SearchResultsChipBarFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
object CategoryBarPatch : BaseBytecodePatch(
|
||||
name = "Hide category bar",
|
||||
description = "Adds an option to hide the category bar in feeds.",
|
||||
dependencies = setOf(
|
||||
SettingsPatch::class,
|
||||
SharedResourceIdPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(
|
||||
FilterBarHeightFingerprint,
|
||||
RelatedChipCloudFingerprint,
|
||||
SearchResultsChipBarFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
FilterBarHeightFingerprint.patch<TwoRegisterInstruction> { register ->
|
||||
"""
|
||||
invoke-static { v$register }, $GENERAL_CLASS_DESCRIPTOR->hideCategoryBarInFeed(I)I
|
||||
move-result v$register
|
||||
"""
|
||||
}
|
||||
|
||||
RelatedChipCloudFingerprint.patch<OneRegisterInstruction>(1) { register ->
|
||||
"invoke-static { v$register }, " +
|
||||
"$GENERAL_CLASS_DESCRIPTOR->hideCategoryBarInRelatedVideo(Landroid/view/View;)V"
|
||||
}
|
||||
|
||||
SearchResultsChipBarFingerprint.patch<OneRegisterInstruction>(-1, -2) { register ->
|
||||
"""
|
||||
invoke-static { v$register }, $GENERAL_CLASS_DESCRIPTOR->hideCategoryBarInSearchResults(I)I
|
||||
move-result v$register
|
||||
"""
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"SETTINGS: HIDE_CATEGORY_BAR"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide category bar")
|
||||
|
||||
}
|
||||
|
||||
private fun <RegisterInstruction : OneRegisterInstruction> MethodFingerprint.patch(
|
||||
insertIndexOffset: Int = 0,
|
||||
hookRegisterOffset: Int = 0,
|
||||
instructions: (Int) -> String
|
||||
) =
|
||||
resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
|
||||
val insertIndex = endIndex + insertIndexOffset
|
||||
val register =
|
||||
getInstruction<RegisterInstruction>(endIndex + hookRegisterOffset).registerA
|
||||
|
||||
addInstructions(insertIndex, instructions(register))
|
||||
}
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.channellistsubmenu
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patches.shared.litho.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.general.channellistsubmenu.fingerprints.ChannelListSubMenuFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
object ChannelListSubMenuPatch : BaseBytecodePatch(
|
||||
name = "Hide channel avatar section",
|
||||
description = "Adds an option to hide the channel avatar section of the subscription feed.",
|
||||
dependencies = setOf(
|
||||
LithoFilterPatch::class,
|
||||
SettingsPatch::class,
|
||||
SharedResourceIdPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(ChannelListSubMenuFingerprint)
|
||||
) {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"$COMPONENTS_PATH/ChannelListSubMenuFilter;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
ChannelListSubMenuFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
val register = getInstruction<OneRegisterInstruction>(endIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
endIndex + 1,
|
||||
"invoke-static {v$register}, $GENERAL_CLASS_DESCRIPTOR->hideChannelListSubMenu(Landroid/view/View;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"SETTINGS: HIDE_CHANNEL_LIST_SUBMENU"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide channel avatar section")
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,246 @@
|
||||
package app.revanced.patches.youtube.general.components
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.shared.litho.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.general.components.fingerprints.AccountListFingerprint
|
||||
import app.revanced.patches.youtube.general.components.fingerprints.AccountListParentFingerprint
|
||||
import app.revanced.patches.youtube.general.components.fingerprints.AccountMenuFingerprint
|
||||
import app.revanced.patches.youtube.general.components.fingerprints.AccountSwitcherAccessibilityLabelFingerprint
|
||||
import app.revanced.patches.youtube.general.components.fingerprints.BottomUiContainerFingerprint
|
||||
import app.revanced.patches.youtube.general.components.fingerprints.CreateSearchSuggestionsFingerprint
|
||||
import app.revanced.patches.youtube.general.components.fingerprints.FloatingMicrophoneFingerprint
|
||||
import app.revanced.patches.youtube.general.components.fingerprints.TrendingSearchConfigFingerprint
|
||||
import app.revanced.patches.youtube.utils.fingerprints.AccountMenuParentFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.AccountSwitcherAccessibility
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.patches.youtube.utils.toolbar.ToolBarHookPatch
|
||||
import app.revanced.patches.youtube.utils.viewgroup.ViewGroupMarginLayoutParamsHookPatch
|
||||
import app.revanced.util.getTargetIndex
|
||||
import app.revanced.util.getTargetIndexWithMethodReferenceName
|
||||
import app.revanced.util.getTargetIndexWithReference
|
||||
import app.revanced.util.getTargetIndexWithReferenceReversed
|
||||
import app.revanced.util.getWideLiteralInstructionIndex
|
||||
import app.revanced.util.literalInstructionBooleanHook
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
object LayoutComponentsPatch : BaseBytecodePatch(
|
||||
name = "Hide layout components",
|
||||
description = "Adds options to hide general layout components.",
|
||||
dependencies = setOf(
|
||||
LithoFilterPatch::class,
|
||||
SettingsPatch::class,
|
||||
SharedResourceIdPatch::class,
|
||||
ToolBarHookPatch::class,
|
||||
ViewGroupMarginLayoutParamsHookPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(
|
||||
AccountListParentFingerprint,
|
||||
AccountMenuParentFingerprint,
|
||||
AccountSwitcherAccessibilityLabelFingerprint,
|
||||
BottomUiContainerFingerprint,
|
||||
CreateSearchSuggestionsFingerprint,
|
||||
FloatingMicrophoneFingerprint,
|
||||
TrendingSearchConfigFingerprint
|
||||
)
|
||||
) {
|
||||
private const val CUSTOM_FILTER_CLASS_DESCRIPTOR =
|
||||
"$COMPONENTS_PATH/CustomFilter;"
|
||||
private const val LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR =
|
||||
"$COMPONENTS_PATH/LayoutComponentsFilter;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
// region patch for hide account menu
|
||||
|
||||
// for you tab
|
||||
AccountListParentFingerprint.resultOrThrow().let { parentResult ->
|
||||
AccountListFingerprint.resolve(context, parentResult.classDef)
|
||||
|
||||
AccountListFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = it.scanResult.patternScanResult!!.startIndex + 3
|
||||
val targetInstruction = getInstruction<FiveRegisterInstruction>(targetIndex)
|
||||
|
||||
addInstruction(
|
||||
targetIndex,
|
||||
"invoke-static {v${targetInstruction.registerC}, v${targetInstruction.registerD}}, " +
|
||||
"$GENERAL_CLASS_DESCRIPTOR->hideAccountList(Landroid/view/View;Ljava/lang/CharSequence;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for tablet and old clients
|
||||
AccountMenuFingerprint.resolve(
|
||||
context,
|
||||
AccountMenuParentFingerprint.resultOrThrow().classDef
|
||||
)
|
||||
AccountMenuFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = it.scanResult.patternScanResult!!.startIndex + 2
|
||||
val targetInstruction = getInstruction<FiveRegisterInstruction>(targetIndex)
|
||||
|
||||
addInstruction(
|
||||
targetIndex,
|
||||
"invoke-static {v${targetInstruction.registerC}, v${targetInstruction.registerD}}, " +
|
||||
"$GENERAL_CLASS_DESCRIPTOR->hideAccountMenu(Landroid/view/View;Ljava/lang/CharSequence;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for hide cast button
|
||||
|
||||
val buttonClass = context.findClass("MediaRouteButton")
|
||||
?: throw PatchException("MediaRouteButton class not found.")
|
||||
|
||||
buttonClass.mutableClass.methods.find { it.name == "setVisibility" }?.apply {
|
||||
addInstructions(
|
||||
0, """
|
||||
invoke-static {p1}, $GENERAL_CLASS_DESCRIPTOR->hideCastButton(I)I
|
||||
move-result p1
|
||||
"""
|
||||
)
|
||||
} ?: throw PatchException("setVisibility method not found.")
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for hide floating microphone
|
||||
|
||||
FloatingMicrophoneFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex + 1, """
|
||||
invoke-static {v$register}, $GENERAL_CLASS_DESCRIPTOR->hideFloatingMicrophone(Z)Z
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for hide handle
|
||||
|
||||
AccountSwitcherAccessibilityLabelFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val constIndex = getWideLiteralInstructionIndex(AccountSwitcherAccessibility)
|
||||
val insertIndex = getTargetIndex(constIndex, Opcode.IF_EQZ)
|
||||
val setVisibilityIndex = getTargetIndexWithMethodReferenceName(insertIndex, "setVisibility")
|
||||
val visibilityRegister = getInstruction<FiveRegisterInstruction>(setVisibilityIndex).registerD
|
||||
|
||||
addInstructions(
|
||||
insertIndex, """
|
||||
invoke-static {v$visibilityRegister}, $GENERAL_CLASS_DESCRIPTOR->hideHandle(I)I
|
||||
move-result v$visibilityRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for hide search term thumbnail
|
||||
|
||||
CreateSearchSuggestionsFingerprint.resultOrThrow().let { result ->
|
||||
result.mutableMethod.apply {
|
||||
val relativeIndex = getWideLiteralInstructionIndex(40)
|
||||
val replaceIndex = getTargetIndexWithReferenceReversed(
|
||||
relativeIndex,
|
||||
"Landroid/widget/ImageView;->setVisibility(I)V"
|
||||
) - 1
|
||||
|
||||
val jumpIndex = getTargetIndexWithReference(
|
||||
relativeIndex,
|
||||
"Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;"
|
||||
) + 4
|
||||
|
||||
val replaceIndexInstruction = getInstruction<TwoRegisterInstruction>(replaceIndex)
|
||||
val replaceIndexReference =
|
||||
getInstruction<ReferenceInstruction>(replaceIndex).reference
|
||||
|
||||
addInstructionsWithLabels(
|
||||
replaceIndex + 1, """
|
||||
invoke-static { }, $GENERAL_CLASS_DESCRIPTOR->hideSearchTermThumbnail()Z
|
||||
move-result v${replaceIndexInstruction.registerA}
|
||||
if-nez v${replaceIndexInstruction.registerA}, :hidden
|
||||
iget-object v${replaceIndexInstruction.registerA}, v${replaceIndexInstruction.registerB}, $replaceIndexReference
|
||||
""", ExternalLabel("hidden", getInstruction(jumpIndex))
|
||||
)
|
||||
removeInstruction(replaceIndex)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for hide snack bar
|
||||
|
||||
BottomUiContainerFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
addInstructionsWithLabels(
|
||||
0, """
|
||||
invoke-static {}, $GENERAL_CLASS_DESCRIPTOR->hideSnackBar()Z
|
||||
move-result v0
|
||||
if-eqz v0, :show
|
||||
return-void
|
||||
""", ExternalLabel("show", getInstruction(0))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for hide toolbar button
|
||||
|
||||
ToolBarHookPatch.injectCall("$GENERAL_CLASS_DESCRIPTOR->hideToolBarButton")
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for hide trending searches
|
||||
|
||||
TrendingSearchConfigFingerprint.literalInstructionBooleanHook(
|
||||
45399984,
|
||||
"$GENERAL_CLASS_DESCRIPTOR->hideTrendingSearches(Z)Z"
|
||||
)
|
||||
|
||||
// endregion
|
||||
|
||||
|
||||
LithoFilterPatch.addFilter(CUSTOM_FILTER_CLASS_DESCRIPTOR)
|
||||
LithoFilterPatch.addFilter(LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE_SCREEN: GENERAL",
|
||||
"SETTINGS: HIDE_LAYOUT_COMPONENTS"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.general.accountmenu.fingerprints
|
||||
package app.revanced.patches.youtube.general.components.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.general.accountmenu.fingerprints
|
||||
package app.revanced.patches.youtube.general.components.fingerprints
|
||||
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.CompactListItem
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.general.accountmenu.fingerprints
|
||||
package app.revanced.patches.youtube.general.components.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.general.handle.fingerprints
|
||||
package app.revanced.patches.youtube.general.components.fingerprints
|
||||
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.AccountSwitcherAccessibility
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.general.snackbar.fingerprints
|
||||
package app.revanced.patches.youtube.general.components.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.general.searchterm.fingerprints
|
||||
package app.revanced.patches.youtube.general.components.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.general.floatingmicrophone.fingerprints
|
||||
package app.revanced.patches.youtube.general.components.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.Fab
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.general.trendingsearches.fingerprints
|
||||
package app.revanced.patches.youtube.general.components.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
@ -1,53 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.crowdfundingbox
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patches.youtube.general.crowdfundingbox.fingerprints.CrowdfundingBoxFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
object CrowdfundingBoxPatch : BaseBytecodePatch(
|
||||
name = "Hide crowdfunding box",
|
||||
description = "Adds an option to hide the crowdfunding box between the player and video description.",
|
||||
dependencies = setOf(
|
||||
SettingsPatch::class,
|
||||
SharedResourceIdPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(CrowdfundingBoxFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
CrowdfundingBoxFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
insertIndex,
|
||||
"invoke-static {v$register}, $GENERAL_CLASS_DESCRIPTOR->hideCrowdfundingBox(Landroid/view/View;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"SETTINGS: HIDE_CROWDFUNDING_BOX"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide crowdfunding box")
|
||||
|
||||
}
|
||||
}
|
@ -28,7 +28,6 @@ object ViewerDiscretionDialogPatch : BaseBytecodePatch(
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Remove viewer discretion dialog")
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
||||
|
@ -1,55 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.floatingmicrophone
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patches.youtube.general.floatingmicrophone.fingerprints.FloatingMicrophoneFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
object FloatingMicrophonePatch : BaseBytecodePatch(
|
||||
name = "Hide floating microphone",
|
||||
description = "Adds an option to hide the floating microphone button when searching.",
|
||||
dependencies = setOf(
|
||||
SettingsPatch::class,
|
||||
SharedResourceIdPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(FloatingMicrophoneFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
FloatingMicrophoneFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex + 1, """
|
||||
invoke-static {v$register}, $GENERAL_CLASS_DESCRIPTOR->hideFloatingMicrophone(Z)Z
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"SETTINGS: HIDE_FLOATING_MICROPHONE"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide floating microphone")
|
||||
|
||||
}
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.handle
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patches.shared.litho.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.general.handle.fingerprints.AccountSwitcherAccessibilityLabelFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.AccountSwitcherAccessibility
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.getTargetIndex
|
||||
import app.revanced.util.getTargetIndexWithMethodReferenceName
|
||||
import app.revanced.util.getWideLiteralInstructionIndex
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
object HandlePatch : BaseBytecodePatch(
|
||||
name = "Hide handle",
|
||||
description = "Adds options to hide the handle in the account switcher and You tab.",
|
||||
dependencies = setOf(
|
||||
LithoFilterPatch::class,
|
||||
SettingsPatch::class,
|
||||
SharedResourceIdPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(AccountSwitcherAccessibilityLabelFingerprint)
|
||||
) {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"$COMPONENTS_PATH/HandlesFilter;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
AccountSwitcherAccessibilityLabelFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val constIndex = getWideLiteralInstructionIndex(AccountSwitcherAccessibility)
|
||||
val insertIndex = getTargetIndex(constIndex, Opcode.IF_EQZ)
|
||||
val setVisibilityIndex = getTargetIndexWithMethodReferenceName(insertIndex, "setVisibility")
|
||||
val visibilityRegister = getInstruction<FiveRegisterInstruction>(setVisibilityIndex).registerD
|
||||
|
||||
addInstructions(
|
||||
insertIndex, """
|
||||
invoke-static {v$visibilityRegister}, $GENERAL_CLASS_DESCRIPTOR->hideHandle(I)I
|
||||
move-result v$visibilityRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"SETTINGS: HIDE_HANDLE"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide handle")
|
||||
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.latestvideosbutton
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patches.youtube.general.latestvideosbutton.fingerprints.LatestVideosButtonFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
object LatestVideosButtonPatch : BaseBytecodePatch(
|
||||
name = "Hide latest videos button",
|
||||
description = "Adds options to hide latest videos button in home feed.",
|
||||
dependencies = setOf(
|
||||
SettingsPatch::class,
|
||||
SharedResourceIdPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(LatestVideosButtonFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
LatestVideosButtonFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
targetIndex + 1,
|
||||
"invoke-static {v$targetRegister}, $GENERAL_CLASS_DESCRIPTOR->hideLatestVideosButton(Landroid/view/View;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"SETTINGS: HIDE_LATEST_VIDEOS_BUTTON"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide latest videos button")
|
||||
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.layout
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patches.shared.litho.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
|
||||
@Suppress("unused")
|
||||
object LayoutComponentsPatch : BaseBytecodePatch(
|
||||
name = "Hide layout components",
|
||||
description = "Adds options to hide general layout components.",
|
||||
dependencies = setOf(
|
||||
LithoFilterPatch::class,
|
||||
SettingsPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE
|
||||
) {
|
||||
private const val CHANNEL_BAR_FILTER_CLASS_DESCRIPTOR =
|
||||
"$COMPONENTS_PATH/ChannelBarFilter;"
|
||||
private const val CUSTOM_FILTER_CLASS_DESCRIPTOR =
|
||||
"$COMPONENTS_PATH/CustomFilter;"
|
||||
private const val LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR =
|
||||
"$COMPONENTS_PATH/LayoutComponentsFilter;"
|
||||
private const val KEYWORD_FILTER_CLASS_NAME =
|
||||
"$COMPONENTS_PATH/KeywordContentFilter;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
LithoFilterPatch.addFilter(CHANNEL_BAR_FILTER_CLASS_DESCRIPTOR)
|
||||
LithoFilterPatch.addFilter(CUSTOM_FILTER_CLASS_DESCRIPTOR)
|
||||
LithoFilterPatch.addFilter(LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR)
|
||||
LithoFilterPatch.addFilter(KEYWORD_FILTER_CLASS_NAME)
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: BOTTOM_PLAYER_SETTINGS",
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"PREFERENCE: PLAYER_SETTINGS",
|
||||
|
||||
"SETTINGS: GENERAL_EXPERIMENTAL_FLAGS",
|
||||
"SETTINGS: HIDE_AUDIO_TRACK_BUTTON",
|
||||
"SETTINGS: HIDE_CHANNEL_BAR_BUTTON",
|
||||
"SETTINGS: HIDE_LAYOUT_COMPONENTS"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide layout components")
|
||||
}
|
||||
}
|
@ -1,18 +1,15 @@
|
||||
package app.revanced.patches.youtube.misc.layoutswitch
|
||||
package app.revanced.patches.youtube.general.layoutswitch
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.misc.layoutswitch.fingerprints.GetFormFactorFingerprint
|
||||
import app.revanced.patches.youtube.utils.fingerprints.LayoutSwitchFingerprint
|
||||
import app.revanced.patches.youtube.general.layoutswitch.fingerprints.GetFormFactorFingerprint
|
||||
import app.revanced.patches.youtube.general.layoutswitch.fingerprints.LayoutSwitchFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.getStringInstructionIndex
|
||||
import app.revanced.util.getTargetIndex
|
||||
import app.revanced.util.getTargetIndexReversed
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
@ -31,18 +28,17 @@ object LayoutSwitchPatch : BaseBytecodePatch(
|
||||
LayoutSwitchFingerprint
|
||||
)
|
||||
) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"$MISC_PATH/LayoutOverridePatch;"
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
// tablet layout
|
||||
// region patch for enable tablet layout
|
||||
|
||||
GetFormFactorFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val jumpIndex = getTargetIndexReversed(Opcode.SGET_OBJECT)
|
||||
|
||||
addInstructionsWithLabels(
|
||||
0, """
|
||||
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->enableTabletLayout()Z
|
||||
invoke-static { }, $GENERAL_CLASS_DESCRIPTOR->enableTabletLayout()Z
|
||||
move-result v0 # Free register
|
||||
if-nez v0, :is_large_form_factor
|
||||
""",
|
||||
@ -54,43 +50,37 @@ object LayoutSwitchPatch : BaseBytecodePatch(
|
||||
}
|
||||
}
|
||||
|
||||
// phone layout
|
||||
// endregion
|
||||
|
||||
// region patch for enable phone layout
|
||||
|
||||
LayoutSwitchFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = getTargetIndex(Opcode.IF_NEZ)
|
||||
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
4, """
|
||||
invoke-static {p0}, $INTEGRATIONS_CLASS_DESCRIPTOR->getLayoutOverride(I)I
|
||||
move-result p0
|
||||
insertIndex, """
|
||||
invoke-static {v$insertRegister}, $GENERAL_CLASS_DESCRIPTOR->enablePhoneLayout(I)I
|
||||
move-result v$insertRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"SETTINGS: EXPERIMENTAL_FLAGS",
|
||||
"PREFERENCE_SCREEN: GENERAL",
|
||||
"PREFERENCE_CATEGORY: GENERAL_EXPERIMENTAL_FLAGS",
|
||||
"SETTINGS: LAYOUT_SWITCH"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Layout switch")
|
||||
|
||||
}
|
||||
|
||||
private fun MutableMethod.injectEnum(
|
||||
enumName: String,
|
||||
fieldName: String
|
||||
) {
|
||||
val stringIndex = getStringInstructionIndex(enumName)
|
||||
val insertIndex = getTargetIndex(stringIndex, Opcode.SPUT_OBJECT)
|
||||
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
insertIndex + 1,
|
||||
"sput-object v$insertRegister, $INTEGRATIONS_CLASS_DESCRIPTOR->$fieldName:Ljava/lang/Enum;"
|
||||
)
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.misc.layoutswitch.fingerprints
|
||||
package app.revanced.patches.youtube.general.layoutswitch.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.utils.fingerprints
|
||||
package app.revanced.patches.youtube.general.layoutswitch.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
@ -42,7 +42,6 @@ object GradientLoadingScreenPatch : BaseBytecodePatch(
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Enable gradient loading screen")
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
||||
|
@ -1,59 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.loadmorebutton
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patches.youtube.general.loadmorebutton.fingerprints.LoadMoreButtonFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
object LoadMoreButtonPatch : BaseBytecodePatch(
|
||||
name = "Hide load more button",
|
||||
description = "Adds an option to hide the button under videos that loads similar videos.",
|
||||
dependencies = setOf(
|
||||
SettingsPatch::class,
|
||||
SharedResourceIdPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(LoadMoreButtonFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
LoadMoreButtonFingerprint.resultOrThrow().let {
|
||||
val getViewMethod =
|
||||
it.mutableClass.methods.find { method ->
|
||||
method.parameters.isEmpty() &&
|
||||
method.returnType == "Landroid/view/View;"
|
||||
}
|
||||
|
||||
getViewMethod?.apply {
|
||||
val targetIndex = implementation!!.instructions.size - 1
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
targetIndex,
|
||||
"invoke-static {v$targetRegister}, $GENERAL_CLASS_DESCRIPTOR->hideLoadMoreButton(Landroid/view/View;)V"
|
||||
)
|
||||
} ?: throw PatchException("Failed to find getView method")
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"SETTINGS: HIDE_LOAD_MORE_BUTTON"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide load more button")
|
||||
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.mixplaylists
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.shared.litho.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.general.mixplaylists.fingerprints.ElementParserFingerprint
|
||||
import app.revanced.patches.youtube.general.mixplaylists.fingerprints.ElementParserParentFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.getTargetIndex
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
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.reference.MethodReference
|
||||
|
||||
@Suppress("unused")
|
||||
object MixPlaylistsPatch : BaseBytecodePatch(
|
||||
name = "Hide mix playlists",
|
||||
description = "Adds an option to hide mix playlists in feed.",
|
||||
dependencies = setOf(
|
||||
LithoFilterPatch::class,
|
||||
SettingsPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(ElementParserParentFingerprint)
|
||||
) {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"$COMPONENTS_PATH/MixPlaylistsFilter;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
ElementParserParentFingerprint.resultOrThrow().let { parentResult ->
|
||||
ElementParserFingerprint.resolve(context, parentResult.classDef)
|
||||
|
||||
ElementParserFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val freeRegister = implementation!!.registerCount - parameters.size - 2
|
||||
val insertIndex = indexOfFirstInstruction {
|
||||
val reference = ((this as? ReferenceInstruction)?.reference as? MethodReference)
|
||||
|
||||
reference?.parameterTypes?.size == 1
|
||||
&& reference.parameterTypes.first() == "[B"
|
||||
&& reference.returnType.startsWith("L")
|
||||
}
|
||||
|
||||
val objectIndex = getTargetIndex(Opcode.MOVE_OBJECT)
|
||||
val objectRegister = getInstruction<TwoRegisterInstruction>(objectIndex).registerA
|
||||
|
||||
val jumpIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
|
||||
addInstructionsWithLabels(
|
||||
insertIndex, """
|
||||
invoke-static {v$objectRegister, v$freeRegister}, $FILTER_CLASS_DESCRIPTOR->filterMixPlaylists(Ljava/lang/Object;[B)Z
|
||||
move-result v$freeRegister
|
||||
if-nez v$freeRegister, :filter
|
||||
""", ExternalLabel("filter", getInstruction(jumpIndex))
|
||||
)
|
||||
|
||||
addInstruction(
|
||||
0,
|
||||
"move-object/from16 v$freeRegister, p3"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"SETTINGS: HIDE_MIX_PLAYLISTS"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide mix playlists")
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
package app.revanced.patches.youtube.general.navigation
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patches.youtube.general.navigation.fingerprints.AutoMotiveFingerprint
|
||||
import app.revanced.patches.youtube.general.navigation.fingerprints.PivotBarChangedFingerprint
|
||||
import app.revanced.patches.youtube.general.navigation.fingerprints.PivotBarSetTextFingerprint
|
||||
import app.revanced.patches.youtube.general.navigation.fingerprints.PivotBarStyleFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.navigation.NavigationBarHookPatch
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.getStringInstructionIndex
|
||||
import app.revanced.util.getTargetIndexWithMethodReferenceName
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
object NavigationBarComponentsPatch : BaseBytecodePatch(
|
||||
name = "Hide navigation bar components",
|
||||
description = "Adds options to hide components related to navigation bar.",
|
||||
dependencies = setOf(
|
||||
SettingsPatch::class,
|
||||
NavigationBarHookPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(
|
||||
AutoMotiveFingerprint,
|
||||
PivotBarChangedFingerprint,
|
||||
PivotBarSetTextFingerprint,
|
||||
PivotBarStyleFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
// region patch for enable narrow navigation buttons
|
||||
|
||||
arrayOf(
|
||||
PivotBarChangedFingerprint,
|
||||
PivotBarStyleFingerprint
|
||||
).forEach { fingerprint ->
|
||||
fingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = it.scanResult.patternScanResult!!.startIndex + 1
|
||||
val register = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
targetIndex + 1, """
|
||||
invoke-static {v$register}, $GENERAL_CLASS_DESCRIPTOR->enableNarrowNavigationButton(Z)Z
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for hide navigation buttons
|
||||
|
||||
AutoMotiveFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = getStringInstructionIndex("Android Automotive") - 1
|
||||
val register = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex, """
|
||||
invoke-static {v$register}, $GENERAL_CLASS_DESCRIPTOR->switchCreateWithNotificationButton(Z)Z
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for hide navigation label
|
||||
|
||||
PivotBarSetTextFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = getTargetIndexWithMethodReferenceName("setText")
|
||||
val targetRegister = getInstruction<FiveRegisterInstruction>(targetIndex).registerC
|
||||
|
||||
addInstruction(
|
||||
targetIndex,
|
||||
"invoke-static {v$targetRegister}, $GENERAL_CLASS_DESCRIPTOR->hideNavigationLabel(Landroid/widget/TextView;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
|
||||
// Hook navigation button created, in order to hide them.
|
||||
NavigationBarHookPatch.hookNavigationButtonCreated(GENERAL_CLASS_DESCRIPTOR)
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE_SCREEN: GENERAL",
|
||||
"SETTINGS: HIDE_NAVIGATION_COMPONENTS"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.navigation.navigationbuttons.fingerprints
|
||||
package app.revanced.patches.youtube.general.navigation.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.navigation.tabletnavbar.fingerprints
|
||||
package app.revanced.patches.youtube.general.navigation.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.navigation.label.fingerprints
|
||||
package app.revanced.patches.youtube.general.navigation.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.navigation.tabletnavbar.fingerprints
|
||||
package app.revanced.patches.youtube.general.navigation.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
@ -1,71 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.searchterm
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.general.searchterm.fingerprints.CreateSearchSuggestionsFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.getTargetIndexWithReference
|
||||
import app.revanced.util.getTargetIndexWithReferenceReversed
|
||||
import app.revanced.util.getWideLiteralInstructionIndex
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
object SearchTermThumbnailPatch : BaseBytecodePatch(
|
||||
name = "Hide search term thumbnail",
|
||||
description = "Adds an option to hide thumbnails in the search term history.",
|
||||
dependencies = setOf(SettingsPatch::class),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(CreateSearchSuggestionsFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
CreateSearchSuggestionsFingerprint.resultOrThrow().let { result ->
|
||||
result.mutableMethod.apply {
|
||||
val relativeIndex = getWideLiteralInstructionIndex(40)
|
||||
val replaceIndex = getTargetIndexWithReferenceReversed(
|
||||
relativeIndex,
|
||||
"Landroid/widget/ImageView;->setVisibility(I)V"
|
||||
) - 1
|
||||
|
||||
val jumpIndex = getTargetIndexWithReference(
|
||||
relativeIndex,
|
||||
"Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;"
|
||||
) + 4
|
||||
|
||||
val replaceIndexInstruction = getInstruction<TwoRegisterInstruction>(replaceIndex)
|
||||
val replaceIndexReference =
|
||||
getInstruction<ReferenceInstruction>(replaceIndex).reference
|
||||
|
||||
addInstructionsWithLabels(
|
||||
replaceIndex + 1, """
|
||||
invoke-static { }, $GENERAL_CLASS_DESCRIPTOR->hideSearchTermThumbnail()Z
|
||||
move-result v${replaceIndexInstruction.registerA}
|
||||
if-nez v${replaceIndexInstruction.registerA}, :hidden
|
||||
iget-object v${replaceIndexInstruction.registerA}, v${replaceIndexInstruction.registerB}, $replaceIndexReference
|
||||
""", ExternalLabel("hidden", getInstruction(jumpIndex))
|
||||
)
|
||||
removeInstruction(replaceIndex)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"SETTINGS: HIDE_SEARCH_TERM_THUMBNAIL"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide search term thumbnail")
|
||||
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.snackbar
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.general.snackbar.fingerprints.BottomUiContainerFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
|
||||
@Suppress("unused")
|
||||
object SnackBarPatch : BaseBytecodePatch(
|
||||
name = "Hide snack bar",
|
||||
description = "Adds an option to hide the snack bar action popup.",
|
||||
dependencies = setOf(SettingsPatch::class),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(BottomUiContainerFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
BottomUiContainerFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
addInstructionsWithLabels(
|
||||
0, """
|
||||
invoke-static {}, $GENERAL_CLASS_DESCRIPTOR->hideSnackBar()Z
|
||||
move-result v0
|
||||
if-eqz v0, :show
|
||||
return-void
|
||||
""", ExternalLabel("show", getInstruction(0))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"SETTINGS: HIDE_SNACK_BAR"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide snack bar")
|
||||
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.songsearch
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patches.youtube.general.songsearch.fingerprints.VoiceSearchConfigFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
|
||||
@Suppress("unused")
|
||||
object SongSearchPatch : BaseBytecodePatch(
|
||||
name = "Enable song search",
|
||||
description = "Adds an option to enable song search in the voice search screen.",
|
||||
dependencies = setOf(SettingsPatch::class),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(VoiceSearchConfigFingerprint),
|
||||
use = false
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
VoiceSearchConfigFingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
addInstructions(
|
||||
0, """
|
||||
invoke-static { }, $GENERAL_CLASS_DESCRIPTOR->enableSongSearch()Z
|
||||
move-result v0
|
||||
return v0
|
||||
"""
|
||||
)
|
||||
}
|
||||
} ?: throw PatchException("This version is not supported. Please use YouTube 18.30.37 or later.")
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"SETTINGS: ENABLE_SONG_SEARCH"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Enable song search")
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.songsearch.fingerprints
|
||||
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||
|
||||
/**
|
||||
* This fingerprint is compatible with YouTube v18.30.37+
|
||||
*/
|
||||
internal object VoiceSearchConfigFingerprint : LiteralValueFingerprint(
|
||||
returnType = "Z",
|
||||
literalSupplier = { 45417109 }
|
||||
)
|
@ -1,62 +1,59 @@
|
||||
package app.revanced.patches.youtube.general.channelprofile
|
||||
package app.revanced.patches.youtube.general.splashanimation
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patches.shared.litho.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.general.channelprofile.fingerprints.DefaultsTabsBarFingerprint
|
||||
import app.revanced.patches.youtube.general.splashanimation.fingerprints.SplashAnimationFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TabsBarTextTabView
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.DarkSplashAnimation
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.getTargetIndexReversed
|
||||
import app.revanced.util.getWideLiteralInstructionIndex
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
object ChannelProfileComponentsPatch : BaseBytecodePatch(
|
||||
name = "Hide channel profile components",
|
||||
description = "Adds an option to hide channel profile components.",
|
||||
object SplashAnimationPatch : BaseBytecodePatch(
|
||||
name = "Disable splash animation",
|
||||
description = "Adds an option to disable splash animation.",
|
||||
dependencies = setOf(
|
||||
LithoFilterPatch::class,
|
||||
SettingsPatch::class,
|
||||
SharedResourceIdPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(DefaultsTabsBarFingerprint)
|
||||
fingerprints = setOf(SplashAnimationFingerprint)
|
||||
) {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"$COMPONENTS_PATH/ChannelProfileFilter;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
DefaultsTabsBarFingerprint.resultOrThrow().let {
|
||||
SplashAnimationFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val viewIndex = getWideLiteralInstructionIndex(TabsBarTextTabView) + 2
|
||||
val viewRegister = getInstruction<OneRegisterInstruction>(viewIndex).registerA
|
||||
val constIndex = getWideLiteralInstructionIndex(DarkSplashAnimation)
|
||||
val targetIndex = getTargetIndexReversed(constIndex, Opcode.INVOKE_STATIC) + 2
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex - 1).registerA
|
||||
|
||||
addInstruction(
|
||||
viewIndex + 1,
|
||||
"sput-object v$viewRegister, $FILTER_CLASS_DESCRIPTOR->channelTabView:Landroid/view/View;"
|
||||
addInstructions(
|
||||
targetIndex, """
|
||||
invoke-static {v$targetRegister}, $GENERAL_CLASS_DESCRIPTOR->disableSplashAnimation(Z)Z
|
||||
move-result v$targetRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"SETTINGS: HIDE_CHANNEL_PROFILE_COMPONENTS"
|
||||
"SETTINGS: DISABLE_SPLASH_ANIMATION"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide channel profile components")
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package app.revanced.patches.youtube.general.splashanimation.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.DarkSplashAnimation
|
||||
import app.revanced.util.containsWideLiteralInstructionIndex
|
||||
|
||||
internal object SplashAnimationFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
parameters = listOf("Landroid/os/Bundle;"),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.name == "onCreate"
|
||||
&& methodDef.containsWideLiteralInstructionIndex(DarkSplashAnimation)
|
||||
}
|
||||
)
|
@ -1,8 +1,8 @@
|
||||
package app.revanced.patches.youtube.misc.spoofappversion
|
||||
package app.revanced.patches.youtube.general.spoofappversion
|
||||
|
||||
import app.revanced.patches.shared.spoofappversion.BaseSpoofAppVersionPatch
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
|
||||
object SpoofAppVersionBytecodePatch : BaseSpoofAppVersionPatch(
|
||||
"$MISC_PATH/SpoofAppVersionPatch;->getVersionOverride(Ljava/lang/String;)Ljava/lang/String;"
|
||||
"$GENERAL_CLASS_DESCRIPTOR->getVersionOverride(Ljava/lang/String;)Ljava/lang/String;"
|
||||
)
|
@ -1,9 +1,8 @@
|
||||
package app.revanced.patches.youtube.misc.spoofappversion
|
||||
package app.revanced.patches.youtube.general.spoofappversion
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.copyXmlNode
|
||||
import app.revanced.util.patch.BaseResourcePatch
|
||||
import org.w3c.dom.Element
|
||||
|
||||
@ -20,32 +19,27 @@ object SpoofAppVersionPatch : BaseResourcePatch(
|
||||
) {
|
||||
override fun execute(context: ResourceContext) {
|
||||
|
||||
/**
|
||||
* Copy arrays
|
||||
*/
|
||||
context.copyXmlNode("youtube/spoofappversion/host", "values/arrays.xml", "resources")
|
||||
|
||||
if (SettingsPatch.upward1834) {
|
||||
context.appendChild(
|
||||
arrayOf(
|
||||
"revanced_spoof_app_version_target_entry" to "@string/revanced_spoof_app_version_target_entry_18_33_40",
|
||||
"revanced_spoof_app_version_target_entry_value" to "18.33.40",
|
||||
"revanced_spoof_app_version_target_entries" to "@string/revanced_spoof_app_version_target_entry_18_33_40",
|
||||
"revanced_spoof_app_version_target_entry_values" to "18.33.40",
|
||||
)
|
||||
)
|
||||
|
||||
if (SettingsPatch.upward1839) {
|
||||
context.appendChild(
|
||||
arrayOf(
|
||||
"revanced_spoof_app_version_target_entry" to "@string/revanced_spoof_app_version_target_entry_18_38_45",
|
||||
"revanced_spoof_app_version_target_entry_value" to "18.38.45"
|
||||
"revanced_spoof_app_version_target_entries" to "@string/revanced_spoof_app_version_target_entry_18_38_45",
|
||||
"revanced_spoof_app_version_target_entry_values" to "18.38.45"
|
||||
)
|
||||
)
|
||||
|
||||
if (SettingsPatch.upward1849) {
|
||||
context.appendChild(
|
||||
arrayOf(
|
||||
"revanced_spoof_app_version_target_entry" to "@string/revanced_spoof_app_version_target_entry_18_48_39",
|
||||
"revanced_spoof_app_version_target_entry_value" to "18.48.39"
|
||||
"revanced_spoof_app_version_target_entries" to "@string/revanced_spoof_app_version_target_entry_18_48_39",
|
||||
"revanced_spoof_app_version_target_entry_values" to "18.48.39"
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -57,13 +51,13 @@ object SpoofAppVersionPatch : BaseResourcePatch(
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"SETTINGS: EXPERIMENTAL_FLAGS",
|
||||
"PREFERENCE_SCREEN: GENERAL",
|
||||
"PREFERENCE_CATEGORY: GENERAL_EXPERIMENTAL_FLAGS",
|
||||
"SETTINGS: SPOOF_APP_VERSION"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Spoof app version")
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
|
||||
private fun ResourceContext.appendChild(entryArray: Array<Pair<String, String>>) {
|
@ -6,8 +6,6 @@ import app.revanced.patches.youtube.general.startpage.fingerprints.StartActivity
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch.contexts
|
||||
import app.revanced.util.copyXmlNode
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
|
||||
@ -29,22 +27,16 @@ object ChangeStartPagePatch : BaseBytecodePatch(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy arrays
|
||||
*/
|
||||
contexts.copyXmlNode("youtube/startpage/host", "values/arrays.xml", "resources")
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"PREFERENCE_SCREEN: GENERAL",
|
||||
"SETTINGS: CHANGE_START_PAGE"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Change start page")
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
||||
|
@ -1,64 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.suggestionshelf
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patches.shared.litho.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.general.suggestionshelf.fingerprints.BreakingNewsFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
|
||||
import app.revanced.patches.youtube.utils.navbarindex.NavBarIndexHookPatch
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
object SuggestionsShelfPatch : BaseBytecodePatch(
|
||||
name = "Hide suggestions shelf",
|
||||
description = "Adds an option to hide the suggestions shelf in feed.",
|
||||
dependencies = setOf(
|
||||
LithoFilterPatch::class,
|
||||
NavBarIndexHookPatch::class,
|
||||
SettingsPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(BreakingNewsFingerprint)
|
||||
) {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"$COMPONENTS_PATH/SuggestionsShelfFilter;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
/**
|
||||
* Only used to tablet layout.
|
||||
*/
|
||||
BreakingNewsFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
targetIndex + 1,
|
||||
"invoke-static {v$targetRegister}, $FILTER_CLASS_DESCRIPTOR->hideBreakingNewsShelf(Landroid/view/View;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"SETTINGS: HIDE_SUGGESTIONS_SHELF"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide suggestions shelf")
|
||||
|
||||
}
|
||||
}
|
@ -75,8 +75,7 @@ object TabletMiniPlayerPatch : BaseBytecodePatch(
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Enable tablet mini player")
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
|
||||
private fun MutableMethod.hook(index: Int) {
|
||||
|
@ -1,37 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.toolbar
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.patches.youtube.utils.toolbar.ToolBarHookPatch
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
|
||||
@Suppress("unused")
|
||||
object ToolBarButtonPatch : BaseBytecodePatch(
|
||||
name = "Hide toolbar button",
|
||||
description = "Adds an option to hide the button in the toolbar.",
|
||||
dependencies = setOf(
|
||||
SettingsPatch::class,
|
||||
ToolBarHookPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
ToolBarHookPatch.injectCall("$GENERAL_CLASS_DESCRIPTOR->hideToolBarButton")
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"SETTINGS: HIDE_TOOLBAR_BUTTON"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide toolbar button")
|
||||
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
package app.revanced.patches.youtube.general.trendingsearches
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patches.youtube.general.trendingsearches.fingerprints.TrendingSearchConfigFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.literalInstructionBooleanHook
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
|
||||
@Suppress("unused")
|
||||
object TrendingSearchesPatch : BaseBytecodePatch(
|
||||
name = "Hide trending searches",
|
||||
description = "Adds an option to hide trending searches in the search bar.",
|
||||
dependencies = setOf(SettingsPatch::class),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(TrendingSearchConfigFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
TrendingSearchConfigFingerprint.literalInstructionBooleanHook(
|
||||
45399984,
|
||||
"$GENERAL_CLASS_DESCRIPTOR->hideTrendingSearches(Z)Z"
|
||||
)
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE: GENERAL_SETTINGS",
|
||||
"SETTINGS: HIDE_TRENDING_SEARCHES"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide trending searches")
|
||||
|
||||
}
|
||||
}
|
@ -86,8 +86,7 @@ object WideSearchBarPatch : BaseBytecodePatch(
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Enable wide search bar")
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -28,6 +28,6 @@ object AnimatedButtonBackgroundPatch : BaseResourcePatch(
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide animated button background")
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
@ -9,7 +9,6 @@ import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.copyResources
|
||||
import app.revanced.util.patch.BaseResourcePatch
|
||||
import org.w3c.dom.Element
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
|
||||
@ -141,14 +140,6 @@ object CustomBrandingIconPatch : BaseResourcePatch(
|
||||
context.copyResources("$resourcePath/monochrome", resourceGroup)
|
||||
}
|
||||
|
||||
// disable splash animation.
|
||||
context.xmlEditor["res/values-v31/styles.xml"].use { editor ->
|
||||
val tags = editor.file.getElementsByTagName("item")
|
||||
List(tags.length) { tags.item(it) as Element }
|
||||
.filter { it.getAttribute("name").contains("android:windowSplashScreenAnimatedIcon") }
|
||||
.forEach { it.parentNode.removeChild(it) }
|
||||
}
|
||||
|
||||
context.updatePatchStatusIcon(appIconValue)
|
||||
}
|
||||
} ?: throw PatchException("Invalid app icon path.")
|
||||
|
@ -5,7 +5,6 @@ import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
|
||||
import app.revanced.patches.shared.elements.StringsElementsUtils.removeStringsElements
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.LANGUAGE_LIST
|
||||
import app.revanced.patches.youtube.utils.settings.ResourceUtils.updatePatchStatusLabel
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseResourcePatch
|
||||
@ -32,9 +31,7 @@ object CustomBrandingNamePatch : BaseResourcePatch(
|
||||
)
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
|
||||
context.removeStringsElements(
|
||||
LANGUAGE_LIST,
|
||||
arrayOf("application_name")
|
||||
)
|
||||
|
||||
|
@ -21,7 +21,6 @@ object DoubleTapOverlayBackgroundPatch : BaseResourcePatch(
|
||||
arrayOf("tap_bloom_view", "dark_background")
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide double tap overlay filter")
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
@ -9,8 +9,9 @@ import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.copyResources
|
||||
import app.revanced.util.patch.BaseResourcePatch
|
||||
import java.nio.file.Files
|
||||
|
||||
@Suppress("unused")
|
||||
@Suppress("DEPRECATION", "unused")
|
||||
object DoubleTapLengthPatch : BaseResourcePatch(
|
||||
name = "Custom double tap length",
|
||||
description = "Add 'double-tap to seek' value.",
|
||||
@ -30,6 +31,10 @@ object DoubleTapLengthPatch : BaseResourcePatch(
|
||||
val entriesName = "double_tap_length_entries"
|
||||
val entryValueName = "double_tap_length_values"
|
||||
|
||||
val valuesV21Directory = context["res"].resolve("values-v21")
|
||||
if (!valuesV21Directory.isDirectory)
|
||||
Files.createDirectories(valuesV21Directory.toPath())
|
||||
|
||||
/**
|
||||
* Copy arrays
|
||||
*/
|
||||
@ -52,7 +57,6 @@ object DoubleTapLengthPatch : BaseResourcePatch(
|
||||
context.addEntryValues(arrayPath, lengthElements[index], entriesName)
|
||||
}
|
||||
|
||||
SettingsPatch.updatePatchStatus("Custom double tap length")
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
@ -46,10 +46,6 @@ object PiPNotificationPatch : BaseBytecodePatch(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.updatePatchStatus("Disable pip notification")
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
@ -29,7 +29,6 @@ object PlayerButtonBackgroundPatch : BaseResourcePatch(
|
||||
}
|
||||
}
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide player button background")
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
||||
|
@ -1,60 +0,0 @@
|
||||
package app.revanced.patches.youtube.layout.splashanimation
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.copyResources
|
||||
import app.revanced.util.copyXmlNode
|
||||
import app.revanced.util.patch.BaseResourcePatch
|
||||
|
||||
@Suppress("DEPRECATION", "unused")
|
||||
object AddSplashAnimationPatch : BaseResourcePatch(
|
||||
name = "Add splash animation",
|
||||
description = "Adds old style splash animation.",
|
||||
dependencies = setOf(SettingsPatch::class),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
use = false
|
||||
) {
|
||||
override fun execute(context: ResourceContext) {
|
||||
|
||||
/**
|
||||
* avd_anim.xml removed from YouTube v18.19.36+
|
||||
*/
|
||||
val targetXml = context["res"].resolve("drawable").resolve("avd_anim.xml")
|
||||
|
||||
if (!targetXml.exists()) {
|
||||
|
||||
/**
|
||||
* merge Splash animation drawables to main drawables
|
||||
* extract from YouTube v18.18.39
|
||||
*/
|
||||
arrayOf(
|
||||
ResourceGroup(
|
||||
"drawable",
|
||||
"\$\$avd_anim__1__0.xml",
|
||||
"\$\$avd_anim__1__1.xml",
|
||||
"\$\$avd_anim__2__0.xml",
|
||||
"\$\$avd_anim__2__1.xml",
|
||||
"\$\$avd_anim__3__0.xml",
|
||||
"\$\$avd_anim__3__1.xml",
|
||||
"\$avd_anim__0.xml",
|
||||
"\$avd_anim__1.xml",
|
||||
"\$avd_anim__2.xml",
|
||||
"\$avd_anim__3.xml",
|
||||
"\$avd_anim__4.xml",
|
||||
"avd_anim.xml"
|
||||
)
|
||||
).forEach { resourceGroup ->
|
||||
context.copyResources("youtube/splashscreen", resourceGroup)
|
||||
}
|
||||
|
||||
/**
|
||||
* merge Splash animation styles to main styles
|
||||
* extract from YouTube v18.18.39
|
||||
*/
|
||||
context.copyXmlNode("youtube/splashscreen", "values-v31/styles.xml", "resources")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ package app.revanced.patches.youtube.layout.tooltip
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patches.youtube.layout.tooltip.fingerprints.TooltipContentFullscreenFingerprint
|
||||
import app.revanced.patches.youtube.layout.tooltip.fingerprints.TooltipContentViewFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||
@ -18,19 +19,23 @@ object TooltipContentViewPatch : BaseBytecodePatch(
|
||||
SharedResourceIdPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(TooltipContentViewFingerprint)
|
||||
fingerprints = setOf(
|
||||
TooltipContentFullscreenFingerprint,
|
||||
TooltipContentViewFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
TooltipContentViewFingerprint.resultOrThrow().mutableMethod.addInstruction(
|
||||
0,
|
||||
"return-void"
|
||||
)
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.updatePatchStatus("Hide tooltip content")
|
||||
arrayOf(
|
||||
TooltipContentFullscreenFingerprint,
|
||||
TooltipContentViewFingerprint
|
||||
).forEach { fingerprint ->
|
||||
fingerprint.resultOrThrow().mutableMethod.addInstruction(
|
||||
0,
|
||||
"return-void"
|
||||
)
|
||||
}
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
package app.revanced.patches.youtube.layout.tooltip.fingerprints
|
||||
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||
|
||||
internal object TooltipContentFullscreenFingerprint : LiteralValueFingerprint(
|
||||
returnType = "V",
|
||||
literalSupplier = { 45384061 }
|
||||
)
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.misc.translations
|
||||
package app.revanced.patches.youtube.layout.translations
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patches.shared.translations.TranslationsUtils.copyXml
|
||||
@ -43,6 +43,6 @@ object TranslationsPatch : BaseResourcePatch(
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Translations")
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
@ -31,6 +31,6 @@ object VoiceSearchButtonPatch : BaseResourcePatch(
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Hide voice search button")
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +0,0 @@
|
||||
package app.revanced.patches.youtube.misc.codec.audio
|
||||
|
||||
import app.revanced.patches.shared.opus.BaseOpusCodecsPatch
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH
|
||||
|
||||
object ForceOpusCodecBytecodePatch : BaseOpusCodecsPatch(
|
||||
"$MISC_PATH/CodecOverridePatch;->shouldForceOpus()Z"
|
||||
)
|
@ -1,33 +0,0 @@
|
||||
package app.revanced.patches.youtube.misc.codec.audio
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseResourcePatch
|
||||
|
||||
@Suppress("unused")
|
||||
object ForceOpusCodecPatch : BaseResourcePatch(
|
||||
name = "Force opus codec",
|
||||
description = "Adds an option to force the opus audio codec instead of the mp4a audio codec.",
|
||||
dependencies = setOf(
|
||||
ForceOpusCodecBytecodePatch::class,
|
||||
SettingsPatch::class
|
||||
),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE
|
||||
) {
|
||||
override fun execute(context: ResourceContext) {
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"SETTINGS: EXPERIMENTAL_FLAGS",
|
||||
"SETTINGS: ENABLE_OPUS_CODEC"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus("Force opus codec")
|
||||
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user