Compare commits

..

7 Commits

Author SHA1 Message Date
semantic-release-bot
1139f77cb9 chore(release): 2.105.0 [skip ci]
# [2.105.0](https://github.com/revanced/revanced-patches/compare/v2.104.2...v2.105.0) (2022-11-09)

### Features

* **nyx:** `unlock-pro` patch ([#1004](https://github.com/revanced/revanced-patches/issues/1004)) ([f72fd91](5a801b1562))
2022-11-09 12:48:57 +00:00
Jonathan
5a801b1562 feat(nyx): unlock-pro patch (#1004) 2022-11-09 13:46:55 +01:00
OxrxL
7f301090b9 refactor(youtube/general-ads-patch): squash extension classes (#1006) 2022-11-09 06:21:56 +01:00
OxrxL
28a687c605 refactor(youtube/general-ads-patch): remove unused code (#1005) 2022-11-09 01:20:13 +01:00
OxrxL
9b74a08ae1 refactor(youtube/general-ads-patch): removed redundant code (#1003) 2022-11-08 18:10:04 +01:00
semantic-release-bot
1177c41373 chore(release): 2.104.2 [skip ci]
## [2.104.2](https://github.com/revanced/revanced-patches/compare/v2.104.1...v2.104.2) (2022-11-08)

### Bug Fixes

* **youtube/hide-endscreen-cards:** restore functionality ([#993](https://github.com/revanced/revanced-patches/issues/993)) ([38eceb7](be4de62c8f))
2022-11-08 17:05:54 +00:00
OxrxL
be4de62c8f fix(youtube/hide-endscreen-cards): restore functionality (#993)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-11-08 18:04:16 +01:00
17 changed files with 339 additions and 128 deletions

View File

@@ -1,3 +1,17 @@
# [2.105.0](https://github.com/revanced/revanced-patches/compare/v2.104.2...v2.105.0) (2022-11-09)
### Features
* **nyx:** `unlock-pro` patch ([#1004](https://github.com/revanced/revanced-patches/issues/1004)) ([9dd8239](https://github.com/revanced/revanced-patches/commit/9dd82391f3f97247224e09e0143b2272a3d47053))
## [2.104.2](https://github.com/revanced/revanced-patches/compare/v2.104.1...v2.104.2) (2022-11-08)
### Bug Fixes
* **youtube/hide-endscreen-cards:** restore functionality ([#993](https://github.com/revanced/revanced-patches/issues/993)) ([eb1bae2](https://github.com/revanced/revanced-patches/commit/eb1bae2c55e65ad29030dce6746a18662dd0fe25))
## [2.104.1](https://github.com/revanced/revanced-patches/compare/v2.104.0...v2.104.1) (2022-11-07)

View File

@@ -81,6 +81,7 @@ The official Patch bundle provided by ReVanced and the community.
| `hide-shorts-button` | Hides the shorts button on the navigation bar. | 17.43.36 |
| `hide-create-button` | Hides the create button in the navigation bar. | 17.43.36 |
| `disable-startup-shorts-player` | Disables playing YouTube Shorts when launching YouTube. | 17.43.36 |
| `hide-endscreen-cards` | Hides the suggested video cards at the end of a video in fullscreen. | 17.43.36 |
| `hide-cast-button` | Hides the cast button in the video player. | all |
| `sponsorblock` | Integrate SponsorBlock. | 17.43.36 |
| `hide-autoplay-button` | Hides the autoplay button in the video player. | 17.43.36 |
@@ -160,6 +161,14 @@ The official Patch bundle provided by ReVanced and the community.
| `general-reddit-ads` | Removes general ads from the Reddit frontpage and subreddits. | all |
</details>
### 📦 `com.awedea.nyx`
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `unlock-pro` | Unlocks all pro features. | all |
</details>
## 📝 JSON Format

View File

@@ -1,2 +1,2 @@
kotlin.code.style = official
version = 2.104.1
version = 2.105.0

File diff suppressed because one or more lines are too long

View File

@@ -18,17 +18,6 @@ import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
import org.w3c.dom.Node
import java.nio.file.Files
// TODO: this method does not make sense here
internal fun MutableMethodImplementation.injectHideCall(
index: Int,
register: Int
) {
this.addInstruction(
index,
"invoke-static { v$register }, Lapp/revanced/integrations/patches/HideHomeAdsPatch;->HideHomeAds(Landroid/view/View;)V".toInstruction()
)
}
/**
* traverse the class hierarchy starting from the given root class
*

View File

@@ -0,0 +1,9 @@
package app.revanced.patches.nyx.misc.pro.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.awedea.nyx")])
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
internal annotation class UnlockProCompatibility

View File

@@ -0,0 +1,15 @@
package app.revanced.patches.nyx.misc.pro.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.nyx.misc.pro.annotations.UnlockProCompatibility
@Name("check-pro-fingerprint")
@UnlockProCompatibility
@Version("0.0.1")
object CheckProFingerprint : MethodFingerprint(
customFingerprint = { methodDef ->
methodDef.definingClass.endsWith("BillingManager;") && methodDef.name == "isProVersion"
}
)

View File

@@ -0,0 +1,38 @@
package app.revanced.patches.nyx.misc.pro.patch
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.removeInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.nyx.misc.pro.annotations.UnlockProCompatibility
import app.revanced.patches.nyx.misc.pro.fingerprints.CheckProFingerprint
@Patch
@Name("unlock-pro")
@Description("Unlocks all pro features.")
@UnlockProCompatibility
@Version("0.0.1")
class UnlockProPatch : BytecodePatch(
listOf(
CheckProFingerprint
)
) {
override fun execute(context: BytecodeContext): PatchResult {
val method = CheckProFingerprint.result!!.mutableMethod
method.addInstructions(
0,
"""
const/4 v0, 0x1
return v0
"""
)
return PatchResultSuccess()
}
}

View File

@@ -1,45 +0,0 @@
package app.revanced.patches.youtube.ad.general.bytecode.extensions
import app.revanced.patcher.extensions.softCompareTo
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
import org.jf.dexlib2.iface.Method
import org.jf.dexlib2.iface.instruction.Instruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.reference.FieldReference
import org.jf.dexlib2.iface.reference.MethodReference
import org.jf.dexlib2.iface.reference.Reference
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
internal object MethodExtensions {
internal fun MutableClass.findMutableMethodOf(
method: Method
) = this.methods.first {
it.softCompareTo(
ImmutableMethodReference(
method.definingClass, method.name, method.parameters, method.returnType
)
)
}
internal inline fun <reified T : Reference> Instruction.toDescriptor(): String {
val reference = (this as ReferenceInstruction).reference
return when (T::class) {
MethodReference::class -> {
val methodReference = reference as MethodReference
"${methodReference.definingClass}->${methodReference.name}(${
methodReference.parameterTypes.joinToString(
""
) { it }
})${methodReference.returnType}"
}
FieldReference::class -> {
val fieldReference = reference as FieldReference
"${fieldReference.definingClass}->${fieldReference.name}:${fieldReference.type}"
}
else -> throw PatchResultError("Unsupported reference type")
}
}
}

View File

@@ -1,12 +1,12 @@
package app.revanced.patches.youtube.ad.general.bytecode.patch
import app.revanced.extensions.injectHideCall
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.extensions.softCompareTo
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
@@ -18,9 +18,8 @@ import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patcher.util.smali.toInstruction
import app.revanced.patches.youtube.ad.general.annotation.GeneralAdsCompatibility
import app.revanced.patches.youtube.ad.general.bytecode.extensions.MethodExtensions.findMutableMethodOf
import app.revanced.patches.youtube.ad.general.bytecode.extensions.MethodExtensions.toDescriptor
import app.revanced.patches.youtube.ad.general.resource.patch.GeneralResourceAdsPatch
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch
@@ -28,13 +27,18 @@ import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.MutableMethodImplementation
import org.jf.dexlib2.builder.instruction.BuilderInstruction10x
import org.jf.dexlib2.dexbacked.instruction.DexBackedInstruction21c
import org.jf.dexlib2.iface.Method
import org.jf.dexlib2.iface.instruction.Instruction
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.instruction.formats.*
import org.jf.dexlib2.iface.reference.FieldReference
import org.jf.dexlib2.iface.reference.MethodReference
import org.jf.dexlib2.iface.reference.Reference
import org.jf.dexlib2.iface.reference.StringReference
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
@Patch
@DependsOn([ResourceMappingResourcePatch::class, IntegrationsPatch::class, SettingsPatch::class, GeneralResourceAdsPatch::class])
@@ -50,17 +54,12 @@ class GeneralBytecodeAdsPatch : BytecodePatch() {
private val resourceIds = arrayOf(
"ad_attribution",
"reel_multiple_items_shelf",
"info_cards_drawer_header",
"endscreen_element_layout_video",
"endscreen_element_layout_circle",
"endscreen_element_layout_icon",
).map { name ->
ResourceMappingResourcePatch.resourceMappings.single { it.name == name }.id
}
private val stringReferences = arrayOf(
"Claiming to use more elements than provided",
"loadVideo() called on LocalDirector in wrong state",
"LoggingProperties are not in proto format"
)
@@ -210,7 +209,6 @@ class GeneralBytecodeAdsPatch : BytecodePatch() {
// insert hide call to hide the view corresponding to the resource
val viewRegister = (invokeInstruction as Instruction35c).registerC
mutableMethod!!.implementation!!.injectHideCall(insertIndex, viewRegister)
}
resourceIds[1] -> { // reel ads
@@ -227,41 +225,6 @@ class GeneralBytecodeAdsPatch : BytecodePatch() {
val viewRegister = (iPutInstruction as Instruction22c).registerA
mutableMethod!!.implementation!!.injectHideCall(insertIndex, viewRegister)
}
resourceIds[2] -> { // info cards ads
// and is followed by an instruction with the mnemonic INVOKE_VIRTUAL
val removeIndex = index - 1
val invokeInstruction = instructions.elementAt(removeIndex)
if (invokeInstruction.opcode != Opcode.INVOKE_VIRTUAL) return@forEachIndexed
// create proxied method, make sure to not re-resolve() the current class
if (mutableClass == null) mutableClass = context.proxy(classDef).mutableClass
if (mutableMethod == null) mutableMethod =
mutableClass!!.findMutableMethodOf(method)
//ToDo: Add Settings toggle for whatever this is
mutableMethod!!.implementation!!.removeInstruction(removeIndex)
}
resourceIds[3], resourceIds[4], resourceIds[5] -> { // end screen ads
// and is followed by an instruction with the mnemonic IPUT_OBJECT
val insertIndex = index + 7
val invokeInstruction = instructions.elementAt(insertIndex)
if (invokeInstruction.opcode != Opcode.IPUT_OBJECT) return@forEachIndexed
// create proxied method, make sure to not re-resolve() the current class
if (mutableClass == null) mutableClass = context.proxy(classDef).mutableClass
if (mutableMethod == null) mutableMethod =
mutableClass!!.findMutableMethodOf(method)
// TODO: dynamically get registers
mutableMethod!!.addInstructions(
insertIndex, """
const/16 v1, 0x8
invoke-virtual {v0,v1}, Landroid/widget/FrameLayout;->setVisibility(I)V
"""
)
}
}
}
@@ -284,11 +247,7 @@ class GeneralBytecodeAdsPatch : BytecodePatch() {
)
}
stringReferences[1] -> {
// TODO: migrate video ads patch to here if necessary
}
stringReferences[2] -> { // Litho ads
stringReferences[1] -> { // Litho ads
val proxy = context.proxy(classDef)
val proxiedClass = proxy.mutableClass
@@ -356,4 +315,45 @@ class GeneralBytecodeAdsPatch : BytecodePatch() {
instruction.opcode == Opcode.CONST && (instruction as Instruction31i).narrowLiteral == lithoConstant
} ?: false
}
private fun MutableClass.findMutableMethodOf(
method: Method
) = this.methods.first {
it.softCompareTo(
ImmutableMethodReference(
method.definingClass, method.name, method.parameters, method.returnType
)
)
}
private inline fun <reified T : Reference> Instruction.toDescriptor(): String {
val reference = (this as ReferenceInstruction).reference
return when (T::class) {
MethodReference::class -> {
val methodReference = reference as MethodReference
"${methodReference.definingClass}->${methodReference.name}(${
methodReference.parameterTypes.joinToString(
""
) { it }
})${methodReference.returnType}"
}
FieldReference::class -> {
val fieldReference = reference as FieldReference
"${fieldReference.definingClass}->${fieldReference.name}:${fieldReference.type}"
}
else -> throw PatchResultError("Unsupported reference type")
}
}
private fun MutableMethodImplementation.injectHideCall(
index: Int,
register: Int
) {
this.addInstruction(
index,
"invoke-static { v$register }, Lapp/revanced/integrations/patches/HideHomeAdsPatch;->HideHomeAds(Landroid/view/View;)V".toInstruction()
)
}
}

View File

@@ -1,20 +0,0 @@
package app.revanced.patches.youtube.ad.general.bytecode.utils
import app.revanced.patcher.extensions.or
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.iface.MethodImplementation
import org.jf.dexlib2.immutable.ImmutableMethod
import org.jf.dexlib2.immutable.ImmutableMethodParameter
internal object MethodUtils {
internal fun createMutableMethod(
definingClass: String, name: String, returnType: String, parameter: String, implementation: MethodImplementation
) = ImmutableMethod(
definingClass, name, listOf(
ImmutableMethodParameter(
parameter, null, null
)
), returnType, AccessFlags.PRIVATE or AccessFlags.STATIC, null, null, implementation
).toMutable()
}

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.youtube.layout.hideendscreencards.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36")
)]
)
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
internal annotation class HideEndscreenCardsCompatibility

View File

@@ -0,0 +1,28 @@
package app.revanced.patches.youtube.layout.hideendscreencards.bytecode.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.hideendscreencards.annotations.HideEndscreenCardsCompatibility
import app.revanced.patches.youtube.layout.hideendscreencards.resource.patch.HideEndscreenCardsResourcePatch
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
@Name("layout-circle-fingerprint")
@HideEndscreenCardsCompatibility
@Version("0.0.1")
object LayoutCircleFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.CONST,
Opcode.CONST_4,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
),
customFingerprint = { methodDef ->
methodDef.implementation?.instructions?.any { instruction ->
instruction.opcode.ordinal == Opcode.CONST.ordinal &&
(instruction as? WideLiteralInstruction)?.wideLiteral == HideEndscreenCardsResourcePatch.layoutCircle
} == true
}
)

View File

@@ -0,0 +1,28 @@
package app.revanced.patches.youtube.layout.hideendscreencards.bytecode.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.hideendscreencards.annotations.HideEndscreenCardsCompatibility
import app.revanced.patches.youtube.layout.hideendscreencards.resource.patch.HideEndscreenCardsResourcePatch
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
@Name("layout-icon-fingerprint")
@HideEndscreenCardsCompatibility
@Version("0.0.1")
object LayoutIconFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.CONST_4,
Opcode.CONST,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
),
customFingerprint = { methodDef ->
methodDef.implementation?.instructions?.any { instruction ->
instruction.opcode.ordinal == Opcode.CONST.ordinal &&
(instruction as? WideLiteralInstruction)?.wideLiteral == HideEndscreenCardsResourcePatch.layoutIcon
} == true
}
)

View File

@@ -0,0 +1,28 @@
package app.revanced.patches.youtube.layout.hideendscreencards.bytecode.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.hideendscreencards.annotations.HideEndscreenCardsCompatibility
import app.revanced.patches.youtube.layout.hideendscreencards.resource.patch.HideEndscreenCardsResourcePatch
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
@Name("layout-video-fingerprint")
@HideEndscreenCardsCompatibility
@Version("0.0.1")
object LayoutVideoFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.CONST,
Opcode.CONST_4,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
),
customFingerprint = { methodDef ->
methodDef.implementation?.instructions?.any { instruction ->
instruction.opcode.ordinal == Opcode.CONST.ordinal &&
(instruction as? WideLiteralInstruction)?.wideLiteral == HideEndscreenCardsResourcePatch.layoutVideo
} == true
}
)

View File

@@ -0,0 +1,57 @@
package app.revanced.patches.youtube.layout.hideendscreencards.bytecode.patch
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.fingerprint.Fingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.layout.hideendscreencards.annotations.HideEndscreenCardsCompatibility
import app.revanced.patches.youtube.layout.hideendscreencards.bytecode.fingerprints.LayoutCircleFingerprint
import app.revanced.patches.youtube.layout.hideendscreencards.bytecode.fingerprints.LayoutIconFingerprint
import app.revanced.patches.youtube.layout.hideendscreencards.bytecode.fingerprints.LayoutVideoFingerprint
import app.revanced.patches.youtube.layout.hideendscreencards.resource.patch.HideEndscreenCardsResourcePatch
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import org.jf.dexlib2.iface.instruction.formats.Instruction21c
@Patch
@DependsOn([IntegrationsPatch::class, HideEndscreenCardsResourcePatch::class])
@Name("hide-endscreen-cards")
@Description("Hides the suggested video cards at the end of a video in fullscreen.")
@HideEndscreenCardsCompatibility
@Version("0.0.1")
class HideEndscreenCardsPatch : BytecodePatch(
listOf(
LayoutCircleFingerprint,
LayoutIconFingerprint,
LayoutVideoFingerprint,
)
) {
override fun execute(context: BytecodeContext): PatchResult {
fun MethodFingerprint.injectHideCall() {
val layoutResult = result!!
val layoutMethod = layoutResult.mutableMethod
val checkCastIndex = layoutResult.scanResult.patternScanResult!!.endIndex
val viewRegister = (layoutMethod.instruction(checkCastIndex) as Instruction21c).registerA
layoutMethod.addInstruction(
checkCastIndex + 1,
"invoke-static { v$viewRegister }, Lapp/revanced/integrations/patches/HideEndscreenCardsPatch;->hideEndscreen(Landroid/view/View;)V"
)
}
listOf(LayoutCircleFingerprint, LayoutIconFingerprint, LayoutVideoFingerprint).forEach(MethodFingerprint::injectHideCall)
return PatchResultSuccess()
}
}

View File

@@ -0,0 +1,48 @@
package app.revanced.patches.youtube.layout.hideendscreencards.resource.patch
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.youtube.layout.hideendscreencards.annotations.HideEndscreenCardsCompatibility
import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
@Name("hide-endscreen-cards-resource-patch")
@HideEndscreenCardsCompatibility
@DependsOn([SettingsPatch::class, ResourceMappingResourcePatch::class])
@Version("0.0.1")
class HideEndscreenCardsResourcePatch : ResourcePatch {
internal companion object {
var layoutCircle: Long = -1
var layoutIcon: Long = -1
var layoutVideo: Long = -1
}
override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
SwitchPreference(
"revanced_hide_endscreen_cards",
StringResource("revanced_hide_endscreen_cards_title", "Hide end-screen cards"),
true,
StringResource("revanced_hide_endscreen_cards_summary_on", "End-screen cards are hidden"),
StringResource("revanced_hide_endscreen_cards_summary_off", "End-screen cards are shown")
),
)
fun findEndscreenResourceId(name: String) = ResourceMappingResourcePatch.resourceMappings.single {
it.type == "layout" && it.name == "endscreen_element_layout_$name"
}.id
layoutCircle = findEndscreenResourceId("circle")
layoutIcon = findEndscreenResourceId("icon")
layoutVideo = findEndscreenResourceId("video")
return PatchResultSuccess()
}
}