refactor(YouTube/Settings): reorganize settings menu

This commit is contained in:
inotia00 2024-04-19 19:35:04 +09:00
parent 3bb394643e
commit e1fd3c8586
286 changed files with 4843 additions and 7307 deletions

View File

@ -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) {

View File

@ -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(

View File

@ -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>

View File

@ -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
// """
// )
}
}
}
}

View File

@ -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"
)
}

View File

@ -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)
}
}

View File

@ -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"
}
)

View File

@ -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

View File

@ -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

View File

@ -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))
)
}
}
}
}

View File

@ -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"
)

View File

@ -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"
)

View File

@ -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)
}
}

View File

@ -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")
}
}

View File

@ -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 }
)

View File

@ -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))
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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)
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -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"
}
)

View File

@ -32,7 +32,6 @@ object AutoCaptionsPatch : BaseBytecodePatch(
)
)
SettingsPatch.updatePatchStatus("Disable auto captions")
SettingsPatch.updatePatchStatus(this)
}
}

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -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"
}
)

View File

@ -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))
}
}
}

View File

@ -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")
}
}

View File

@ -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)
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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")
}
}

View File

@ -28,7 +28,6 @@ object ViewerDiscretionDialogPatch : BaseBytecodePatch(
)
)
SettingsPatch.updatePatchStatus("Remove viewer discretion dialog")
SettingsPatch.updatePatchStatus(this)
}
}

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -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)
}
}

View File

@ -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

View File

@ -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

View File

@ -42,7 +42,6 @@ object GradientLoadingScreenPatch : BaseBytecodePatch(
)
)
SettingsPatch.updatePatchStatus("Enable gradient loading screen")
SettingsPatch.updatePatchStatus(this)
}
}

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -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)
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -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 }
)

View File

@ -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)
}
}

View File

@ -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)
}
)

View File

@ -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;"
)

View File

@ -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>>) {

View File

@ -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)
}
}

View File

@ -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")
}
}

View File

@ -75,8 +75,7 @@ object TabletMiniPlayerPatch : BaseBytecodePatch(
)
)
SettingsPatch.updatePatchStatus("Enable tablet mini player")
SettingsPatch.updatePatchStatus(this)
}
private fun MutableMethod.hook(index: Int) {

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -86,8 +86,7 @@ object WideSearchBarPatch : BaseBytecodePatch(
)
)
SettingsPatch.updatePatchStatus("Enable wide search bar")
SettingsPatch.updatePatchStatus(this)
}
/**

View File

@ -28,6 +28,6 @@ object AnimatedButtonBackgroundPatch : BaseResourcePatch(
)
)
SettingsPatch.updatePatchStatus("Hide animated button background")
SettingsPatch.updatePatchStatus(this)
}
}

View File

@ -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.")

View File

@ -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")
)

View File

@ -21,7 +21,6 @@ object DoubleTapOverlayBackgroundPatch : BaseResourcePatch(
arrayOf("tap_bloom_view", "dark_background")
)
SettingsPatch.updatePatchStatus("Hide double tap overlay filter")
SettingsPatch.updatePatchStatus(this)
}
}

View File

@ -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)
}
}

View File

@ -46,10 +46,6 @@ object PiPNotificationPatch : BaseBytecodePatch(
}
}
/**
* Add settings
*/
SettingsPatch.updatePatchStatus("Disable pip notification")
SettingsPatch.updatePatchStatus(this)
}
}

View File

@ -29,7 +29,6 @@ object PlayerButtonBackgroundPatch : BaseResourcePatch(
}
}
SettingsPatch.updatePatchStatus("Hide player button background")
SettingsPatch.updatePatchStatus(this)
}
}

View File

@ -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")
}
}
}

View File

@ -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)
}
}

View File

@ -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 }
)

View File

@ -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)
}
}

View File

@ -31,6 +31,6 @@ object VoiceSearchButtonPatch : BaseResourcePatch(
)
)
SettingsPatch.updatePatchStatus("Hide voice search button")
SettingsPatch.updatePatchStatus(this)
}
}

View File

@ -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"
)

View File

@ -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