mirror of
https://github.com/ReVanced/revanced-patches.git
synced 2026-01-28 05:01:03 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e36d72c5c | ||
|
|
6197246e8e | ||
|
|
15a044cae1 | ||
|
|
ede60b994c | ||
|
|
c15cc431d6 | ||
|
|
fb006f87ab | ||
|
|
28206fd804 | ||
|
|
e425e75152 | ||
|
|
69d6c55942 | ||
|
|
f2b29351b4 | ||
|
|
db0b468e71 | ||
|
|
b75e759348 | ||
|
|
83b41322c4 | ||
|
|
8d8878aa08 | ||
|
|
d628674cdd | ||
|
|
23b182ccbb | ||
|
|
4a784ecd6e | ||
|
|
0165b53c6d | ||
|
|
17a0e16087 |
62
CHANGELOG.md
62
CHANGELOG.md
@@ -1,3 +1,65 @@
|
|||||||
|
## [2.43.2](https://github.com/revanced/revanced-patches/compare/v2.43.1...v2.43.2) (2022-08-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* package name for Vanced ([#390](https://github.com/revanced/revanced-patches/issues/390)) ([85206b9](https://github.com/revanced/revanced-patches/commit/85206b99e1399d00e5eaebded8aadc5fb982aaa4))
|
||||||
|
|
||||||
|
## [2.43.1](https://github.com/revanced/revanced-patches/compare/v2.43.0...v2.43.1) (2022-08-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* `Patch` annotation for `client-spoof` patch ([6a8af47](https://github.com/revanced/revanced-patches/commit/6a8af47f2dfb319a53db9b5f9deb0392f10f4185))
|
||||||
|
|
||||||
|
# [2.43.0](https://github.com/revanced/revanced-patches/compare/v2.42.1...v2.43.0) (2022-08-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* `client-spoof` patch ([5512c07](https://github.com/revanced/revanced-patches/commit/5512c072fa4b047849dbea0d2d382dd85e3a0827))
|
||||||
|
|
||||||
|
## [2.42.1](https://github.com/revanced/revanced-patches/compare/v2.42.0...v2.42.1) (2022-08-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* changed default value for autorepeat setting ([#386](https://github.com/revanced/revanced-patches/issues/386)) ([d43add7](https://github.com/revanced/revanced-patches/commit/d43add7c21f0d9f45830476704985755e37d33ef))
|
||||||
|
|
||||||
|
# [2.42.0](https://github.com/revanced/revanced-patches/compare/v2.41.0...v2.42.0) (2022-08-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* default values for settings ([834c4ad](https://github.com/revanced/revanced-patches/commit/834c4add71570d36b645246621ba24da3869d613))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* setting for downloader package name ([965d05c](https://github.com/revanced/revanced-patches/commit/965d05cfa55d7a51f64a11f0219e2867568ba852))
|
||||||
|
* v17.29.34 compatibility for `downloads` patch ([#374](https://github.com/revanced/revanced-patches/issues/374)) ([d81f1af](https://github.com/revanced/revanced-patches/commit/d81f1af327e0d7471f410811af46da34ddfb1bb4))
|
||||||
|
|
||||||
|
# [2.41.0](https://github.com/revanced/revanced-patches/compare/v2.40.2...v2.41.0) (2022-08-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* `downloads` patch ([#215](https://github.com/revanced/revanced-patches/issues/215)) ([304fbac](https://github.com/revanced/revanced-patches/commit/304fbacab22538fb0945f564e061783b47120120))
|
||||||
|
|
||||||
|
## [2.40.2](https://github.com/revanced/revanced-patches/compare/v2.40.1...v2.40.2) (2022-08-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* correct title for `tablet-miniplayer` setting switch ([6af6c02](https://github.com/revanced/revanced-patches/commit/6af6c02154d170153093bd846dfcb7a6205dd6fa))
|
||||||
|
|
||||||
|
## [2.40.1](https://github.com/revanced/revanced-patches/compare/v2.40.0...v2.40.1) (2022-08-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add missing switch for `tablet-mini-player` patch ([244a1b2](https://github.com/revanced/revanced-patches/commit/244a1b2cb9f77272dc62287a4a34a487b0289295))
|
||||||
|
|
||||||
# [2.40.0](https://github.com/revanced/revanced-patches/compare/v2.39.1...v2.40.0) (2022-08-22)
|
# [2.40.0](https://github.com/revanced/revanced-patches/compare/v2.39.1...v2.40.0) (2022-08-22)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ Official patches by ReVanced
|
|||||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|:--------:|:--------------:|:-----------------:|
|
|:--------:|:--------------:|:-----------------:|
|
||||||
| `swipe-controls` | Adds volume and brightness swipe controls. | 17.32.35 |
|
| `swipe-controls` | Adds volume and brightness swipe controls. | 17.32.35 |
|
||||||
|
| `downloads` | Enables downloading music and videos from YouTube. | 17.32.35 |
|
||||||
| `seekbar-tapping` | Enables tap-to-seek on the seekbar of the video player. | 17.32.35 |
|
| `seekbar-tapping` | Enables tap-to-seek on the seekbar of the video player. | 17.32.35 |
|
||||||
| `amoled` | Enables pure black theme. | 17.32.35 |
|
| `amoled` | Enables pure black theme. | 17.32.35 |
|
||||||
| `disable-create-button` | Hides the create button in the navigation bar. | 17.32.35 |
|
| `disable-create-button` | Hides the create button in the navigation bar. | 17.32.35 |
|
||||||
@@ -83,9 +84,10 @@ Official patches by ReVanced
|
|||||||
| `enable-wide-searchbar` | Replaces the search icon with a wide search bar. This will hide the YouTube logo when active. | 17.32.35 |
|
| `enable-wide-searchbar` | Replaces the search icon with a wide search bar. This will hide the YouTube logo when active. | 17.32.35 |
|
||||||
| `tablet-mini-player` | Enables the tablet mini player layout. | 17.32.35 |
|
| `tablet-mini-player` | Enables the tablet mini player layout. | 17.32.35 |
|
||||||
| `minimized-playback` | Enables minimized and background playback. | 17.32.35 |
|
| `minimized-playback` | Enables minimized and background playback. | 17.32.35 |
|
||||||
|
| `client-spoof` | Spoofs the YouTube or Vanced client to prevent playback issues. | all |
|
||||||
| `custom-video-buffer` | Lets you change the buffers of videos. | 17.32.35 |
|
| `custom-video-buffer` | Lets you change the buffers of videos. | 17.32.35 |
|
||||||
| `always-autorepeat` | Always repeats the playing video again. | 17.32.35 |
|
| `always-autorepeat` | Always repeats the playing video again. | 17.32.35 |
|
||||||
| `microg-support` | Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG | 17.32.35 |
|
| `microg-support` | Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG. | 17.32.35 |
|
||||||
| `settings` | Adds settings for ReVanced to YouTube. | all |
|
| `settings` | Adds settings for ReVanced to YouTube. | all |
|
||||||
| `enable-debugging` | Enables app debugging by patching the manifest file. | all |
|
| `enable-debugging` | Enables app debugging by patching the manifest file. | all |
|
||||||
| `custom-playback-speed` | Adds more video playback speed options. | 17.32.35 |
|
| `custom-playback-speed` | Adds more video playback speed options. | 17.32.35 |
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
version = 2.40.0
|
version = 2.43.2
|
||||||
|
|||||||
@@ -73,11 +73,11 @@ class GeneralBytecodeAdsPatch : BytecodePatch() {
|
|||||||
override fun execute(data: BytecodeData): PatchResult {
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
SettingsPatch.PreferenceScreen.ADS.addPreferences(
|
SettingsPatch.PreferenceScreen.ADS.addPreferences(
|
||||||
SwitchPreference(
|
SwitchPreference(
|
||||||
"revanced_home_ads_enabled",
|
"revanced_home_ads_removal",
|
||||||
StringResource("revanced_home_ads_enabled_title", "Hide home ads"),
|
StringResource("revanced_home_ads_removal_title", "Remove home ads"),
|
||||||
true,
|
true,
|
||||||
StringResource("revanced_home_ads_enabled_summary_on", "Home ads are shown"),
|
StringResource("revanced_home_ads_removal_summary_on", "Home ads are hidden"),
|
||||||
StringResource("revanced_home_ads_enabled_summary_off", "Home ads are hidden")
|
StringResource("revanced_home_ads_removal_summary_off", "Home ads are shown")
|
||||||
),
|
),
|
||||||
SwitchPreference(
|
SwitchPreference(
|
||||||
"revanced_adremover_ad_removal",
|
"revanced_adremover_ad_removal",
|
||||||
|
|||||||
@@ -33,11 +33,11 @@ class VideoAdsPatch : BytecodePatch(
|
|||||||
override fun execute(data: BytecodeData): PatchResult {
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
SettingsPatch.PreferenceScreen.ADS.addPreferences(
|
SettingsPatch.PreferenceScreen.ADS.addPreferences(
|
||||||
SwitchPreference(
|
SwitchPreference(
|
||||||
"revanced_video_ads_enabled",
|
"revanced_video_ads_removal",
|
||||||
StringResource("revanced_video_ads_enabled_title", "Hide video ads"),
|
StringResource("revanced_video_ads_removal_title", "Hide video ads"),
|
||||||
true,
|
true,
|
||||||
StringResource("revanced_video_ads_enabled_summary_on", "Video ads are hidden"),
|
StringResource("revanced_video_ads_removal_summary_on", "Video ads are hidden"),
|
||||||
StringResource("revanced_video_ads_enabled_summary_off", "Video ads are shown")
|
StringResource("revanced_video_ads_removal_summary_off", "Video ads are shown")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package app.revanced.patches.youtube.interaction.downloads.annotation
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[Package(
|
||||||
|
"com.google.android.youtube", arrayOf("17.27.39", "17.29.34", "17.32.35")
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class DownloadsCompatibility
|
||||||
|
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package app.revanced.patches.youtube.interaction.downloads.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.impl.BytecodeData
|
||||||
|
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.patch.impl.BytecodePatch
|
||||||
|
import app.revanced.patches.youtube.interaction.downloads.annotation.DownloadsCompatibility
|
||||||
|
import app.revanced.patches.youtube.interaction.downloads.resource.patch.DownloadsResourcePatch
|
||||||
|
import app.revanced.patches.youtube.misc.playercontrols.bytecode.patch.PlayerControlsBytecodePatch
|
||||||
|
import app.revanced.patches.youtube.misc.videoid.patch.VideoIdPatch
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("downloads")
|
||||||
|
@DependsOn([DownloadsResourcePatch::class, PlayerControlsBytecodePatch::class, VideoIdPatch::class])
|
||||||
|
@Description("Enables downloading music and videos from YouTube.")
|
||||||
|
@DownloadsCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class DownloadsBytecodePatch : BytecodePatch() {
|
||||||
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
val integrationsPackage = "app/revanced/integrations"
|
||||||
|
val classDescriptor = "L$integrationsPackage/videoplayer/DownloadButton;"
|
||||||
|
|
||||||
|
/*
|
||||||
|
initialize the control
|
||||||
|
*/
|
||||||
|
|
||||||
|
val initializeDownloadsDescriptor = "$classDescriptor->initializeDownloadButton(Ljava/lang/Object;)V"
|
||||||
|
PlayerControlsBytecodePatch.initializeControl(initializeDownloadsDescriptor)
|
||||||
|
|
||||||
|
/*
|
||||||
|
add code to change the visibility of the control
|
||||||
|
*/
|
||||||
|
|
||||||
|
val changeVisibilityDescriptor = "$classDescriptor->changeVisibility(Z)V"
|
||||||
|
PlayerControlsBytecodePatch.injectVisibilityCheckCall(changeVisibilityDescriptor)
|
||||||
|
|
||||||
|
/*
|
||||||
|
add code to change to update the video id
|
||||||
|
*/
|
||||||
|
|
||||||
|
val setVideoIdDescriptor =
|
||||||
|
"L$integrationsPackage/patches/downloads/DownloadsPatch;->setVideoId(Ljava/lang/String;)V"
|
||||||
|
VideoIdPatch.injectCall(setVideoIdDescriptor)
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package app.revanced.patches.youtube.interaction.downloads.resource.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.impl.ResourceData
|
||||||
|
import app.revanced.patcher.patch.PatchResult
|
||||||
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.DependsOn
|
||||||
|
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||||
|
import app.revanced.patches.youtube.interaction.downloads.annotation.DownloadsCompatibility
|
||||||
|
import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch
|
||||||
|
import app.revanced.patches.youtube.misc.playercontrols.resource.patch.BottomControlsResourcePatch
|
||||||
|
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||||
|
import app.revanced.patches.youtube.misc.settings.framework.components.impl.*
|
||||||
|
import app.revanced.util.resources.ResourceUtils
|
||||||
|
import app.revanced.util.resources.ResourceUtils.Settings.mergeStrings
|
||||||
|
import app.revanced.util.resources.ResourceUtils.copyResources
|
||||||
|
|
||||||
|
@Name("downloads-resource-patch")
|
||||||
|
@DependsOn([BottomControlsResourcePatch::class, FixLocaleConfigErrorPatch::class, SettingsPatch::class])
|
||||||
|
@Description("Makes necessary changes to resources for the download button.")
|
||||||
|
@DownloadsCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class DownloadsResourcePatch : ResourcePatch() {
|
||||||
|
override fun execute(data: ResourceData): PatchResult {
|
||||||
|
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
|
||||||
|
PreferenceScreen(
|
||||||
|
"revanced_downloads",
|
||||||
|
StringResource("revanced_downloads_title", "Download settings"),
|
||||||
|
listOf(
|
||||||
|
SwitchPreference(
|
||||||
|
"revanced_downloads",
|
||||||
|
StringResource("revanced_downloads_enabled_title", "Show download button"),
|
||||||
|
true,
|
||||||
|
StringResource("revanced_downloads_enabled_summary_on", "Download button is visible"),
|
||||||
|
StringResource("revanced_downloads_enabled_summary_off", "Download button is hidden")
|
||||||
|
),
|
||||||
|
TextPreference(
|
||||||
|
"revanced_downloads_package_name",
|
||||||
|
StringResource("revanced_downloads_package_name_title", "Downloader package name"),
|
||||||
|
InputType.STRING,
|
||||||
|
"org.schabi.newpipe" /* NewPipe */,
|
||||||
|
StringResource("revanced_downloads_package_name_summary", "Package name of the downloader app such as NewPipe\\'s or PowerTube\\'s")
|
||||||
|
)
|
||||||
|
),
|
||||||
|
StringResource("revanced_downloads_summary", "Settings related to downloads")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy strings
|
||||||
|
*/
|
||||||
|
|
||||||
|
data.mergeStrings("downloads/host/values/strings.xml")
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy resources
|
||||||
|
*/
|
||||||
|
|
||||||
|
data.copyResources("downloads", ResourceUtils.ResourceGroup("drawable", "revanced_yt_download_button.xml"))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add download button node
|
||||||
|
*/
|
||||||
|
|
||||||
|
BottomControlsResourcePatch.addControls("downloads/host/layout/${BottomControlsResourcePatch.TARGET_RESOURCE_NAME}")
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package app.revanced.patches.youtube.interaction.swipecontrols.patch.resource
|
package app.revanced.patches.youtube.interaction.swipecontrols.patch.resource
|
||||||
|
|
||||||
import app.revanced.extensions.injectResources
|
|
||||||
import app.revanced.patcher.annotation.Name
|
import app.revanced.patcher.annotation.Name
|
||||||
import app.revanced.patcher.annotation.Version
|
import app.revanced.patcher.annotation.Version
|
||||||
import app.revanced.patcher.data.impl.ResourceData
|
import app.revanced.patcher.data.impl.ResourceData
|
||||||
@@ -11,6 +10,8 @@ import app.revanced.patcher.patch.impl.ResourcePatch
|
|||||||
import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility
|
import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility
|
||||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.*
|
import app.revanced.patches.youtube.misc.settings.framework.components.impl.*
|
||||||
|
import app.revanced.util.resources.ResourceUtils
|
||||||
|
import app.revanced.util.resources.ResourceUtils.copyResources
|
||||||
|
|
||||||
@Name("swipe-controls-resource-patch")
|
@Name("swipe-controls-resource-patch")
|
||||||
@DependsOn([SettingsPatch::class])
|
@DependsOn([SettingsPatch::class])
|
||||||
@@ -93,16 +94,15 @@ class SwipeControlsResourcePatch : ResourcePatch() {
|
|||||||
|
|
||||||
val resourcesDir = "swipecontrols"
|
val resourcesDir = "swipecontrols"
|
||||||
|
|
||||||
data.injectResources(
|
data.copyResources(
|
||||||
this.javaClass.classLoader,
|
"swipecontrols",
|
||||||
resourcesDir,
|
ResourceUtils.ResourceGroup(
|
||||||
"drawable",
|
"drawable",
|
||||||
listOf(
|
"ic_sc_brightness_auto.xml",
|
||||||
"ic_sc_brightness_auto",
|
"ic_sc_brightness_manual.xml",
|
||||||
"ic_sc_brightness_manual",
|
"ic_sc_volume_mute.xml",
|
||||||
"ic_sc_volume_mute",
|
"ic_sc_volume_normal.xml"
|
||||||
"ic_sc_volume_normal"
|
)
|
||||||
).map { "$it.xml" }
|
|
||||||
)
|
)
|
||||||
return PatchResultSuccess()
|
return PatchResultSuccess()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ class CreateButtonRemoverPatch : BytecodePatch(
|
|||||||
"revanced_create_button_enabled",
|
"revanced_create_button_enabled",
|
||||||
StringResource("revanced_create_button_enabled_title", "Show create button"),
|
StringResource("revanced_create_button_enabled_title", "Show create button"),
|
||||||
false,
|
false,
|
||||||
StringResource("revanced_create_button_summary_on", "Create button is shown."),
|
StringResource("revanced_create_button_summary_on", "Create button is shown"),
|
||||||
StringResource("revanced_create_button_summary_off", "Create button is hidden.")
|
StringResource("revanced_create_button_summary_off", "Create button is hidden")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatc
|
|||||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.Preference
|
import app.revanced.patches.youtube.misc.settings.framework.components.impl.Preference
|
||||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||||
import app.revanced.util.resources.ResourceUtils.iterateXmlNodeChildren
|
import app.revanced.util.resources.ResourceUtils.Settings.mergeStrings
|
||||||
|
|
||||||
@DependsOn([FixLocaleConfigErrorPatch::class, SettingsPatch::class])
|
@DependsOn([FixLocaleConfigErrorPatch::class, SettingsPatch::class])
|
||||||
@Name("return-youtube-dislike-resource-patch")
|
@Name("return-youtube-dislike-resource-patch")
|
||||||
@@ -35,12 +35,7 @@ class ReturnYouTubeDislikeResourcePatch : ResourcePatch() {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
// merge strings
|
// merge strings
|
||||||
data.iterateXmlNodeChildren("returnyoutubedislike/host/values/strings.xml", "resources") {
|
data.mergeStrings("returnyoutubedislike/host/values/strings.xml")
|
||||||
// TODO: figure out why this is needed
|
|
||||||
if (!it.hasAttributes()) return@iterateXmlNodeChildren
|
|
||||||
val attributes = it.attributes
|
|
||||||
SettingsPatch.addString(attributes.getNamedItem("name")!!.nodeValue!!, it.textContent!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
return PatchResultSuccess()
|
return PatchResultSuccess()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
|
||||||
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
|
|
||||||
|
|
||||||
@Name("show-player-controls-fingerprint")
|
|
||||||
@MatchingMethod(
|
|
||||||
"LYouTubeControlsOverlay;", "ac"
|
|
||||||
)
|
|
||||||
@DirectPatternScanMethod
|
|
||||||
@SponsorBlockCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object ShowPlayerControlsFingerprint : MethodFingerprint(
|
|
||||||
"V", null, listOf("Z","Z"), null, null
|
|
||||||
)
|
|
||||||
@@ -23,6 +23,7 @@ import app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints.*
|
|||||||
import app.revanced.patches.youtube.layout.sponsorblock.resource.patch.SponsorBlockResourcePatch
|
import app.revanced.patches.youtube.layout.sponsorblock.resource.patch.SponsorBlockResourcePatch
|
||||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||||
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
|
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
|
||||||
|
import app.revanced.patches.youtube.misc.playercontrols.bytecode.patch.PlayerControlsBytecodePatch
|
||||||
import app.revanced.patches.youtube.misc.videoid.patch.VideoIdPatch
|
import app.revanced.patches.youtube.misc.videoid.patch.VideoIdPatch
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
@@ -38,7 +39,7 @@ import org.jf.dexlib2.util.MethodUtil
|
|||||||
|
|
||||||
@Patch
|
@Patch
|
||||||
@DependsOn(
|
@DependsOn(
|
||||||
dependencies = [IntegrationsPatch::class, ResourceIdMappingProviderResourcePatch::class, SponsorBlockResourcePatch::class, VideoIdPatch::class]
|
dependencies = [PlayerControlsBytecodePatch::class, IntegrationsPatch::class, ResourceIdMappingProviderResourcePatch::class, SponsorBlockResourcePatch::class, VideoIdPatch::class]
|
||||||
)
|
)
|
||||||
@Name("sponsorblock")
|
@Name("sponsorblock")
|
||||||
@Description("Integrate SponsorBlock.")
|
@Description("Integrate SponsorBlock.")
|
||||||
@@ -171,8 +172,7 @@ class SponsorBlockBytecodePatch : BytecodePatch(
|
|||||||
/*
|
/*
|
||||||
Voting & Shield button
|
Voting & Shield button
|
||||||
*/
|
*/
|
||||||
ShowPlayerControlsFingerprint.resolve(data, data.classes.find { it.type.endsWith("YouTubeControlsOverlay;") }!!)
|
val controlsMethodResult = PlayerControlsBytecodePatch.showPlayerControlsFingerprintResult
|
||||||
val controlsMethodResult = ShowPlayerControlsFingerprint.result!!
|
|
||||||
|
|
||||||
val controlsLayoutStubResourceId =
|
val controlsLayoutStubResourceId =
|
||||||
ResourceIdMappingProviderResourcePatch.resourceMappings.single { it.type == "id" && it.name == "controls_layout_stub" }.id
|
ResourceIdMappingProviderResourcePatch.resourceMappings.single { it.type == "id" && it.name == "controls_layout_stub" }.id
|
||||||
@@ -217,12 +217,8 @@ class SponsorBlockBytecodePatch : BytecodePatch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// change visibility of the buttons
|
// change visibility of the buttons
|
||||||
controlsMethodResult.mutableMethod.addInstructions(
|
PlayerControlsBytecodePatch.injectVisibilityCheckCall("Lapp/revanced/integrations/sponsorblock/ShieldButton;->changeVisibility(Z)V")
|
||||||
0, """
|
PlayerControlsBytecodePatch.injectVisibilityCheckCall("Lapp/revanced/integrations/sponsorblock/VotingButton;->changeVisibility(Z)V")
|
||||||
invoke-static {p1}, Lapp/revanced/integrations/sponsorblock/ShieldButton;->changeVisibility(Z)V
|
|
||||||
invoke-static {p1}, Lapp/revanced/integrations/sponsorblock/VotingButton;->changeVisibility(Z)V
|
|
||||||
""".trimIndent()
|
|
||||||
)
|
|
||||||
|
|
||||||
// set SegmentHelperLayout.context to the player layout instance
|
// set SegmentHelperLayout.context to the player layout instance
|
||||||
val instanceRegister = 0
|
val instanceRegister = 0
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
|||||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.Preference
|
import app.revanced.patches.youtube.misc.settings.framework.components.impl.Preference
|
||||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||||
import app.revanced.util.resources.ResourceUtils
|
import app.revanced.util.resources.ResourceUtils
|
||||||
|
import app.revanced.util.resources.ResourceUtils.Settings.mergeStrings
|
||||||
import app.revanced.util.resources.ResourceUtils.copyResources
|
import app.revanced.util.resources.ResourceUtils.copyResources
|
||||||
import app.revanced.util.resources.ResourceUtils.copyXmlNode
|
import app.revanced.util.resources.ResourceUtils.copyXmlNode
|
||||||
import app.revanced.util.resources.ResourceUtils.iterateXmlNodeChildren
|
|
||||||
|
|
||||||
@Name("sponsorblock-resource-patch")
|
@Name("sponsorblock-resource-patch")
|
||||||
@SponsorBlockCompatibility
|
@SponsorBlockCompatibility
|
||||||
@@ -40,20 +40,7 @@ class SponsorBlockResourcePatch : ResourcePatch() {
|
|||||||
/*
|
/*
|
||||||
merge SponsorBlock strings to main strings
|
merge SponsorBlock strings to main strings
|
||||||
*/
|
*/
|
||||||
data.iterateXmlNodeChildren("sponsorblock/host/values/strings.xml", "resources") {
|
data.mergeStrings("sponsorblock/host/values/strings.xml")
|
||||||
// TODO: figure out why this is needed
|
|
||||||
if (!it.hasAttributes()) return@iterateXmlNodeChildren
|
|
||||||
|
|
||||||
val attributes = it.attributes
|
|
||||||
val key = attributes.getNamedItem("name")!!.nodeValue!!
|
|
||||||
val value = it.textContent!!
|
|
||||||
|
|
||||||
// all strings of SponsorBlock which have this attribute have the attribute value false,
|
|
||||||
// hence a null check suffices
|
|
||||||
val formatted = attributes.getNamedItem("formatted") == null
|
|
||||||
|
|
||||||
SettingsPatch.addString(key, value, formatted)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
merge SponsorBlock drawables to main drawables
|
merge SponsorBlock drawables to main drawables
|
||||||
|
|||||||
@@ -19,10 +19,13 @@ import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPla
|
|||||||
import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerOverrideNoContextFingerprint
|
import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerOverrideNoContextFingerprint
|
||||||
import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerResponseModelSizeCheckFingerprint
|
import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerResponseModelSizeCheckFingerprint
|
||||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||||
|
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.iface.instruction.OneRegisterInstruction
|
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
|
||||||
@Patch
|
@Patch
|
||||||
@DependsOn([IntegrationsPatch::class])
|
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
|
||||||
@Name("tablet-mini-player")
|
@Name("tablet-mini-player")
|
||||||
@Description("Enables the tablet mini player layout.")
|
@Description("Enables the tablet mini player layout.")
|
||||||
@TabletMiniPlayerCompatibility
|
@TabletMiniPlayerCompatibility
|
||||||
@@ -34,6 +37,14 @@ class TabletMiniPlayerPatch : BytecodePatch(
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun execute(data: BytecodeData): PatchResult {
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(SwitchPreference(
|
||||||
|
"revanced_tablet_miniplayer",
|
||||||
|
StringResource("revanced_tablet_miniplayer_title", "Enable the tablet Mini-player"),
|
||||||
|
false,
|
||||||
|
StringResource("revanced_tablet_miniplayer_summary_on", "Tablet Mini-player is enabled"),
|
||||||
|
StringResource("revanced_tablet_miniplayer_summary_off", "Tablet Mini-player is disabled")
|
||||||
|
))
|
||||||
|
|
||||||
// first resolve the fingerprints via the parent fingerprint
|
// first resolve the fingerprints via the parent fingerprint
|
||||||
val miniPlayerClass = MiniPlayerDimensionsCalculatorFingerprint.result!!.classDef
|
val miniPlayerClass = MiniPlayerDimensionsCalculatorFingerprint.result!!.classDef
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class AutoRepeatPatch : BytecodePatch(
|
|||||||
SwitchPreference(
|
SwitchPreference(
|
||||||
"revanced_pref_auto_repeat",
|
"revanced_pref_auto_repeat",
|
||||||
StringResource("revanced_auto_repeat_enabled_title", "Enable auto-repeat"),
|
StringResource("revanced_auto_repeat_enabled_title", "Enable auto-repeat"),
|
||||||
true,
|
false,
|
||||||
StringResource("revanced_auto_repeat_summary_on", "Auto-repeat is enabled"),
|
StringResource("revanced_auto_repeat_summary_on", "Auto-repeat is enabled"),
|
||||||
StringResource("revanced_auto_repeat_summary_off", "Auto-repeat is disabled")
|
StringResource("revanced_auto_repeat_summary_off", "Auto-repeat is disabled")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package app.revanced.patches.youtube.misc.clientspoof.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[
|
||||||
|
Package("com.google.android.youtube", arrayOf()),
|
||||||
|
Package("com.vanced.android.youtube", arrayOf())
|
||||||
|
]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class ClientSpoofCompatibility
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package app.revanced.patches.youtube.misc.clientspoof.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import app.revanced.patches.youtube.misc.clientspoof.annotations.ClientSpoofCompatibility
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Name("user-agent-header-builder-fingerprint")
|
||||||
|
@ClientSpoofCompatibility
|
||||||
|
@DirectPatternScanMethod
|
||||||
|
@Version("0.0.1")
|
||||||
|
object UserAgentHeaderBuilderFingerprint : MethodFingerprint(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
listOf("L", "L", "L"),
|
||||||
|
listOf(Opcode.MOVE_RESULT_OBJECT, Opcode.INVOKE_VIRTUAL),
|
||||||
|
listOf("(Linux; U; Android "),
|
||||||
|
)
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package app.revanced.patches.youtube.misc.clientspoof.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.impl.BytecodeData
|
||||||
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.extensions.instruction
|
||||||
|
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.patch.impl.BytecodePatch
|
||||||
|
import app.revanced.patches.youtube.misc.clientspoof.annotations.ClientSpoofCompatibility
|
||||||
|
import app.revanced.patches.youtube.misc.clientspoof.fingerprints.UserAgentHeaderBuilderFingerprint
|
||||||
|
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||||
|
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("client-spoof")
|
||||||
|
@Description("Spoofs the YouTube or Vanced client to prevent playback issues.")
|
||||||
|
@DependsOn([IntegrationsPatch::class])
|
||||||
|
@ClientSpoofCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class ClientSpoofPatch : BytecodePatch(
|
||||||
|
listOf(UserAgentHeaderBuilderFingerprint)
|
||||||
|
) {
|
||||||
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
val result = UserAgentHeaderBuilderFingerprint.result!!
|
||||||
|
val method = result.mutableMethod
|
||||||
|
|
||||||
|
val insertIndex = result.patternScanResult!!.endIndex
|
||||||
|
val packageNameRegister = (method.instruction(insertIndex) as FiveRegisterInstruction).registerD
|
||||||
|
|
||||||
|
val originalPackageName = "com.google.android.youtube"
|
||||||
|
method.addInstructions(insertIndex, "const-string v$packageNameRegister, \"$originalPackageName\"")
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ import app.revanced.patcher.patch.annotations.Patch
|
|||||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
|
||||||
import app.revanced.patches.youtube.layout.castbutton.patch.HideCastButtonPatch
|
import app.revanced.patches.youtube.layout.castbutton.patch.HideCastButtonPatch
|
||||||
|
import app.revanced.patches.youtube.misc.clientspoof.patch.ClientSpoofPatch
|
||||||
import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility
|
import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility
|
||||||
import app.revanced.patches.youtube.misc.microg.fingerprints.*
|
import app.revanced.patches.youtube.misc.microg.fingerprints.*
|
||||||
import app.revanced.patches.youtube.misc.microg.patch.resource.MicroGResourcePatch
|
import app.revanced.patches.youtube.misc.microg.patch.resource.MicroGResourcePatch
|
||||||
@@ -32,10 +33,11 @@ import org.jf.dexlib2.immutable.reference.ImmutableStringReference
|
|||||||
[
|
[
|
||||||
MicroGResourcePatch::class,
|
MicroGResourcePatch::class,
|
||||||
HideCastButtonPatch::class,
|
HideCastButtonPatch::class,
|
||||||
|
ClientSpoofPatch::class
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@Name("microg-support")
|
@Name("microg-support")
|
||||||
@Description("Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG")
|
@Description("Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG.")
|
||||||
@MicroGPatchCompatibility
|
@MicroGPatchCompatibility
|
||||||
@Version("0.0.1")
|
@Version("0.0.1")
|
||||||
class MicroGBytecodePatch : BytecodePatch(
|
class MicroGBytecodePatch : BytecodePatch(
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package app.revanced.patches.youtube.misc.playercontrols.annotation
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[Package(
|
||||||
|
"com.google.android.youtube", arrayOf("17.27.39", "17.32.35")
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class PlayerControlsCompatibility
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package app.revanced.patches.youtube.misc.playercontrols.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.impl.BytecodeData
|
||||||
|
import app.revanced.patcher.extensions.addInstruction
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||||
|
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
|
||||||
|
import app.revanced.patcher.patch.PatchResult
|
||||||
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.DependsOn
|
||||||
|
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||||
|
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
|
||||||
|
import app.revanced.patches.youtube.misc.playercontrols.annotation.PlayerControlsCompatibility
|
||||||
|
import app.revanced.patches.youtube.misc.playercontrols.fingerprints.BottomControlsInflateFingerprint
|
||||||
|
import app.revanced.patches.youtube.misc.playercontrols.fingerprints.PlayerControlsVisibilityFingerprint
|
||||||
|
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
|
||||||
|
@Name("player-controls-bytecode-patch")
|
||||||
|
@DependsOn([ResourceIdMappingProviderResourcePatch::class])
|
||||||
|
@Description("Manages the code for the player controls of the YouTube player.")
|
||||||
|
@PlayerControlsCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class PlayerControlsBytecodePatch : BytecodePatch(
|
||||||
|
listOf(PlayerControlsVisibilityFingerprint)
|
||||||
|
) {
|
||||||
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
showPlayerControlsFingerprintResult = PlayerControlsVisibilityFingerprint.result!!
|
||||||
|
|
||||||
|
bottomUiContainerResourceId = ResourceIdMappingProviderResourcePatch
|
||||||
|
.resourceMappings
|
||||||
|
.single { it.type == "id" && it.name == "bottom_ui_container_stub" }.id
|
||||||
|
|
||||||
|
// TODO: another solution is required, this is hacky
|
||||||
|
listOf(BottomControlsInflateFingerprint).resolve(data, data.classes)
|
||||||
|
inflateFingerprintResult = BottomControlsInflateFingerprint.result!!
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal companion object {
|
||||||
|
var bottomUiContainerResourceId: Long = 0
|
||||||
|
|
||||||
|
lateinit var showPlayerControlsFingerprintResult: MethodFingerprintResult
|
||||||
|
|
||||||
|
private var inflateFingerprintResult: MethodFingerprintResult? = null
|
||||||
|
set(fingerprint) {
|
||||||
|
field = fingerprint!!.also {
|
||||||
|
moveToRegisterInstructionIndex = it.patternScanResult!!.endIndex
|
||||||
|
viewRegister =
|
||||||
|
(it.mutableMethod.implementation!!.instructions[moveToRegisterInstructionIndex] as OneRegisterInstruction).registerA
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var moveToRegisterInstructionIndex: Int = 0
|
||||||
|
private var viewRegister: Int = 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects the code to change the visibility of controls.
|
||||||
|
* @param descriptor The descriptor of the method which should be called.
|
||||||
|
*/
|
||||||
|
fun injectVisibilityCheckCall(descriptor: String) {
|
||||||
|
showPlayerControlsFingerprintResult.mutableMethod.addInstruction(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
invoke-static {p1}, $descriptor
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects the code to initialize the controls.
|
||||||
|
* @param descriptor The descriptor of the method which should be calleed.
|
||||||
|
*/
|
||||||
|
fun initializeControl(descriptor: String) {
|
||||||
|
inflateFingerprintResult!!.mutableMethod.addInstruction(
|
||||||
|
moveToRegisterInstructionIndex + 1,
|
||||||
|
"invoke-static {v$viewRegister}, $descriptor"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package app.revanced.patches.youtube.misc.playercontrols.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
||||||
|
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import app.revanced.patches.youtube.misc.playercontrols.annotation.PlayerControlsCompatibility
|
||||||
|
import app.revanced.patches.youtube.misc.playercontrols.bytecode.patch.PlayerControlsBytecodePatch
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||||
|
|
||||||
|
@Name("bottom-controls-inflate-fingerprint")
|
||||||
|
@MatchingMethod(
|
||||||
|
"Lknf;", "a"
|
||||||
|
)
|
||||||
|
@DirectPatternScanMethod
|
||||||
|
@PlayerControlsCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object BottomControlsInflateFingerprint : MethodFingerprint(
|
||||||
|
null, null, null, listOf(
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT
|
||||||
|
), null,
|
||||||
|
{ methodDef ->
|
||||||
|
methodDef.implementation?.instructions?.any { instruction ->
|
||||||
|
(instruction as? WideLiteralInstruction)?.wideLiteral == PlayerControlsBytecodePatch.bottomUiContainerResourceId
|
||||||
|
} == true
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package app.revanced.patches.youtube.misc.playercontrols.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
||||||
|
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import app.revanced.patches.youtube.misc.playercontrols.annotation.PlayerControlsCompatibility
|
||||||
|
|
||||||
|
@Name("player-controls-visibility-fingerprint")
|
||||||
|
@MatchingMethod(
|
||||||
|
"LYouTubeControlsOverlay;", "ag"
|
||||||
|
)
|
||||||
|
@DirectPatternScanMethod
|
||||||
|
@PlayerControlsCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object PlayerControlsVisibilityFingerprint : MethodFingerprint(
|
||||||
|
"V", null, listOf("Z", "Z"), null, null, { methodDef ->
|
||||||
|
methodDef.definingClass.endsWith("YouTubeControlsOverlay;")
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package app.revanced.patches.youtube.misc.playercontrols.resource.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.impl.DomFileEditor
|
||||||
|
import app.revanced.patcher.data.impl.ResourceData
|
||||||
|
import app.revanced.patcher.patch.PatchResult
|
||||||
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.DependsOn
|
||||||
|
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||||
|
import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch
|
||||||
|
import app.revanced.patches.youtube.misc.playercontrols.annotation.PlayerControlsCompatibility
|
||||||
|
import java.io.Closeable
|
||||||
|
|
||||||
|
@Name("bottom-controls-resource-patch")
|
||||||
|
@DependsOn([FixLocaleConfigErrorPatch::class])
|
||||||
|
@Description("Manages the resources for the bottom controls of the YouTube player.")
|
||||||
|
@PlayerControlsCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class BottomControlsResourcePatch : ResourcePatch(), Closeable {
|
||||||
|
override fun execute(data: ResourceData): PatchResult {
|
||||||
|
resourceData = data
|
||||||
|
targetXmlEditor = data.xmlEditor[TARGET_RESOURCE]
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
internal const val TARGET_RESOURCE_NAME = "youtube_controls_bottom_ui_container.xml"
|
||||||
|
private const val TARGET_RESOURCE = "res/layout/$TARGET_RESOURCE_NAME"
|
||||||
|
|
||||||
|
private lateinit var resourceData: ResourceData
|
||||||
|
private lateinit var targetXmlEditor: DomFileEditor
|
||||||
|
|
||||||
|
// The element to which to add the new elements to
|
||||||
|
private var lastLeftOf = "fullscreen_button"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add new controls to the bottom of the YouTube player.
|
||||||
|
* @param hostYouTubeControlsBottomUiResourceName The hosting resource name containing the elements.
|
||||||
|
*/
|
||||||
|
internal fun addControls(hostYouTubeControlsBottomUiResourceName: String) {
|
||||||
|
val sourceXmlEditor =
|
||||||
|
resourceData.xmlEditor[this::class.java.classLoader.getResourceAsStream(
|
||||||
|
hostYouTubeControlsBottomUiResourceName
|
||||||
|
)!!]
|
||||||
|
|
||||||
|
val targetElement =
|
||||||
|
"android.support.constraint.ConstraintLayout"
|
||||||
|
|
||||||
|
val hostElements = sourceXmlEditor.file.getElementsByTagName(targetElement).item(0).childNodes
|
||||||
|
|
||||||
|
val destinationResourceFile = this.targetXmlEditor.file
|
||||||
|
val destinationElement =
|
||||||
|
destinationResourceFile.getElementsByTagName(targetElement).item(0)
|
||||||
|
|
||||||
|
for (index in 1 until hostElements.length) {
|
||||||
|
val element = hostElements.item(index).cloneNode(true)
|
||||||
|
|
||||||
|
// if the element has no attributes theres no point to adding it to the destination
|
||||||
|
if (!element.hasAttributes()) continue
|
||||||
|
|
||||||
|
// set the elements lastLeftOf attribute to the lastLeftOf value
|
||||||
|
val namespace = "@+id"
|
||||||
|
element.attributes.getNamedItem("yt:layout_constraintRight_toLeftOf").nodeValue =
|
||||||
|
"$namespace/$lastLeftOf"
|
||||||
|
|
||||||
|
// set lastLeftOf attribute to the the current element
|
||||||
|
val nameSpaceLength = 4
|
||||||
|
lastLeftOf = element.attributes.getNamedItem("android:id").nodeValue.substring(nameSpaceLength)
|
||||||
|
|
||||||
|
// copy the element
|
||||||
|
destinationResourceFile.adoptNode(element)
|
||||||
|
destinationElement.appendChild(element)
|
||||||
|
}
|
||||||
|
sourceXmlEditor.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
targetXmlEditor.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,11 +2,38 @@ package app.revanced.util.resources
|
|||||||
|
|
||||||
import app.revanced.patcher.data.impl.DomFileEditor
|
import app.revanced.patcher.data.impl.DomFileEditor
|
||||||
import app.revanced.patcher.data.impl.ResourceData
|
import app.revanced.patcher.data.impl.ResourceData
|
||||||
|
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||||
|
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||||
import org.w3c.dom.Node
|
import org.w3c.dom.Node
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.StandardCopyOption
|
import java.nio.file.StandardCopyOption
|
||||||
|
|
||||||
internal object ResourceUtils {
|
internal object ResourceUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settings related utilities
|
||||||
|
*/
|
||||||
|
internal object Settings {
|
||||||
|
/**
|
||||||
|
* Merge strings. This handles [StringResource]s automatically.
|
||||||
|
* @param host The hosting xml resource. Needs to be a valid strings.xml resource.
|
||||||
|
*/
|
||||||
|
internal fun ResourceData.mergeStrings(host: String) {
|
||||||
|
this.iterateXmlNodeChildren(host, "resources") {
|
||||||
|
// TODO: figure out why this is needed
|
||||||
|
if (!it.hasAttributes()) return@iterateXmlNodeChildren
|
||||||
|
|
||||||
|
val attributes = it.attributes
|
||||||
|
val key = attributes.getNamedItem("name")!!.nodeValue!!
|
||||||
|
val value = it.textContent!!
|
||||||
|
|
||||||
|
val formatted = attributes.getNamedItem("formatted") == null
|
||||||
|
|
||||||
|
SettingsPatch.addString(key, value, formatted)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy resources from the current class loader to the resource directory.
|
* Copy resources from the current class loader to the resource directory.
|
||||||
* @param sourceResourceDirectory The source resource directory name.
|
* @param sourceResourceDirectory The source resource directory name.
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:tint="?attr/ytTextPrimary" android:height="24dp" android:width="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||||
|
<path android:fillColor="#ff000000" android:pathData="M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:yt="http://schemas.android.com/apk/res-auto" android:id="@+id/youtube_controls_bottom_ui_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:layoutDirection="ltr">
|
||||||
|
<com.google.android.libraries.youtube.common.ui.TouchImageView android:id="@+id/download_button" android:paddingLeft="12dp" android:paddingTop="22dp" android:paddingRight="12dp" android:paddingBottom="16dp" android:longClickable="false" android:layout_width="60dp" android:layout_height="60dp" android:src="@drawable/revanced_yt_download_button" android:scaleType="center" yt:layout_constraintBottom_toTopOf="@+id/quick_actions_container" yt:layout_constraintRight_toLeftOf="@+id/fullscreen_button" style="@style/YouTubePlayerButton"/>
|
||||||
|
</android.support.constraint.ConstraintLayout>
|
||||||
4
src/main/resources/downloads/host/values/strings.xml
Normal file
4
src/main/resources/downloads/host/values/strings.xml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="downloader_not_installed_warning">is not installed</string>
|
||||||
|
</resources>
|
||||||
Reference in New Issue
Block a user