Compare commits

...

31 Commits

Author SHA1 Message Date
semantic-release-bot
807a7b01d3 chore(release): 2.186.0-dev.3 [skip ci]
# [2.186.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v2.186.0-dev.2...v2.186.0-dev.3) (2023-07-20)

### Bug Fixes

* **Tiktok - Settings:** get instruction registers dynamically ([#2676](https://github.com/ReVanced/revanced-patches/issues/2676)) ([b3ff7ef](b3ff7efdb2))
2023-07-20 17:39:14 +00:00
Vu Hoan Huy
b3ff7efdb2 fix(Tiktok - Settings): get instruction registers dynamically (#2676) 2023-07-20 19:36:41 +02:00
semantic-release-bot
098162173f chore(release): 2.186.0-dev.2 [skip ci]
# [2.186.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.186.0-dev.1...v2.186.0-dev.2) (2023-07-20)

### Bug Fixes

* **YouTube - Theme:** apply custom seekbar color to shorts ([#2670](https://github.com/ReVanced/revanced-patches/issues/2670)) ([a19fa4e](a19fa4e087))

### Features

* **Youtube - Theme:** add a switch to enable/disable custom seekbar color ([#2663](https://github.com/ReVanced/revanced-patches/issues/2663)) ([dd7c663](dd7c663df6))
2023-07-20 17:31:06 +00:00
LisoUseInAIKyrios
a19fa4e087 fix(YouTube - Theme): apply custom seekbar color to shorts (#2670) 2023-07-20 21:28:22 +04:00
LisoUseInAIKyrios
dd7c663df6 feat(Youtube - Theme): add a switch to enable/disable custom seekbar color (#2663) 2023-07-20 21:27:44 +04:00
semantic-release-bot
9bd7773af2 chore(release): 2.186.0-dev.1 [skip ci]
# [2.186.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v2.185.0...v2.186.0-dev.1) (2023-07-20)

### Features

* **Twitter:** remove `Hide view stats` patch ([4e1c9b9](4e1c9b9ec2))
2023-07-20 16:47:25 +00:00
oSumAtrIX
4e1c9b9ec2 feat(Twitter): remove Hide view stats patch
The patch is constrained on a version that is not working properly anymore.
2023-07-20 18:44:08 +02:00
semantic-release-bot
96a6f3f93e chore(release): 2.185.0 [skip ci]
# [2.185.0](https://github.com/ReVanced/revanced-patches/compare/v2.184.0...v2.185.0) (2023-07-20)

### Bug Fixes

* allocate for more than eight `LithoFilter` array items ([#2643](https://github.com/ReVanced/revanced-patches/issues/2643)) ([5de8ee5](5de8ee51c1))
* **Sync for Reddit - Disable ads:** fix compatibility with latest version ([6b2f786](6b2f7862d1))
* **Tiktok - Settings:** bump compatibility ([#2656](https://github.com/ReVanced/revanced-patches/issues/2656)) ([90e32ea](90e32eac54))
* **TikTok - Show seekbar:** fix seekbar not always showing ([#2660](https://github.com/ReVanced/revanced-patches/issues/2660)) ([e4adaeb](e4adaebad4))
* **Trakt - Unlock pro:** constraint to last known working version ([#2662](https://github.com/ReVanced/revanced-patches/issues/2662)) ([9da2bc3](9da2bc32a1))
* **YouTube - Spoof client:** show video time and chapters while using seekbar ([#2607](https://github.com/ReVanced/revanced-patches/issues/2607)) ([7fdc0d2](7fdc0d2a70))
* **youtube/sponsorblock:** fix some segments skipping slightly too late ([#2634](https://github.com/ReVanced/revanced-patches/issues/2634)) ([180c777](180c7775e6))

### Features

* **youtube:** rename `video-speed` to `playback-speed` ([#2642](https://github.com/ReVanced/revanced-patches/issues/2642)) ([75fd96f](75fd96f4c3))
2023-07-20 00:04:46 +00:00
oSumAtrIX
b74611a6ae chore: merge branch dev to main (#2641) 2023-07-20 02:02:15 +02:00
semantic-release-bot
ae40d87bb3 chore(release): 2.185.0-dev.7 [skip ci]
# [2.185.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v2.185.0-dev.6...v2.185.0-dev.7) (2023-07-19)

### Bug Fixes

* **YouTube - Spoof client:** show video time and chapters while using seekbar ([#2607](https://github.com/ReVanced/revanced-patches/issues/2607)) ([7fdc0d2](7fdc0d2a70))
2023-07-19 23:20:29 +00:00
LisoUseInAIKyrios
7fdc0d2a70 fix(YouTube - Spoof client): show video time and chapters while using seekbar (#2607) 2023-07-20 01:17:47 +02:00
semantic-release-bot
1fade09694 chore(release): 2.185.0-dev.6 [skip ci]
# [2.185.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v2.185.0-dev.5...v2.185.0-dev.6) (2023-07-19)

### Bug Fixes

* **Tiktok - Settings:** bump compatibility ([#2656](https://github.com/ReVanced/revanced-patches/issues/2656)) ([90e32ea](90e32eac54))
2023-07-19 23:16:57 +00:00
Vu Hoan Huy
90e32eac54 fix(Tiktok - Settings): bump compatibility (#2656) 2023-07-20 01:13:33 +02:00
semantic-release-bot
a0632c8a92 chore(release): 2.185.0-dev.5 [skip ci]
# [2.185.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v2.185.0-dev.4...v2.185.0-dev.5) (2023-07-19)

### Bug Fixes

* **Trakt - Unlock pro:** constraint to last known working version ([#2662](https://github.com/ReVanced/revanced-patches/issues/2662)) ([9da2bc3](9da2bc32a1))
2023-07-19 22:52:54 +00:00
johnconner122
9da2bc32a1 fix(Trakt - Unlock pro): constraint to last known working version (#2662) 2023-07-20 00:50:16 +02:00
semantic-release-bot
89fed3874f chore(release): 2.185.0-dev.4 [skip ci]
# [2.185.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v2.185.0-dev.3...v2.185.0-dev.4) (2023-07-19)

### Bug Fixes

* **TikTok - Show seekbar:** fix seekbar not always showing ([#2660](https://github.com/ReVanced/revanced-patches/issues/2660)) ([e4adaeb](e4adaebad4))
2023-07-19 12:58:39 +00:00
Vu Hoan Huy
e4adaebad4 fix(TikTok - Show seekbar): fix seekbar not always showing (#2660) 2023-07-19 14:55:17 +02:00
semantic-release-bot
0b78e8377b chore(release): 2.185.0-dev.3 [skip ci]
# [2.185.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v2.185.0-dev.2...v2.185.0-dev.3) (2023-07-17)

### Bug Fixes

* **Sync for Reddit - Disable ads:** fix compatibility with latest version ([6b2f786](6b2f7862d1))
2023-07-17 22:39:26 +00:00
oSumAtrIX
6b2f7862d1 fix(Sync for Reddit - Disable ads): fix compatibility with latest version 2023-07-18 00:36:37 +02:00
Aaronjamt
4668861d65 chore: fix typos (fingereprints -> fingerprints) (#2650) 2023-07-17 15:21:07 +04:00
semantic-release-bot
c5c63537ff chore(release): 2.185.0-dev.2 [skip ci]
# [2.185.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.185.0-dev.1...v2.185.0-dev.2) (2023-07-15)

### Bug Fixes

* allocate for more than eight `LithoFilter` array items ([#2643](https://github.com/ReVanced/revanced-patches/issues/2643)) ([5de8ee5](5de8ee51c1))
2023-07-15 21:27:19 +00:00
johnconner122
5de8ee51c1 fix: allocate for more than eight LithoFilter array items (#2643) 2023-07-15 23:24:34 +02:00
semantic-release-bot
65087833b0 chore(release): 2.185.0-dev.1 [skip ci]
# [2.185.0-dev.1](https://github.com/revanced/revanced-patches/compare/v2.184.1-dev.1...v2.185.0-dev.1) (2023-07-15)

### Features

* **youtube:** rename `video-speed` to `playback-speed` ([#2642](https://github.com/revanced/revanced-patches/issues/2642)) ([75fd96f](75fd96f4c3))
2023-07-15 12:36:34 +00:00
KAZI MMT
75fd96f4c3 feat(youtube): rename video-speed to playback-speed (#2642) 2023-07-15 16:32:39 +04:00
semantic-release-bot
2cac5b1b74 chore(release): 2.184.1-dev.1 [skip ci]
## [2.184.1-dev.1](https://github.com/revanced/revanced-patches/compare/v2.184.0...v2.184.1-dev.1) (2023-07-14)

### Bug Fixes

* **youtube/sponsorblock:** fix some segments skipping slightly too late ([#2634](https://github.com/revanced/revanced-patches/issues/2634)) ([180c777](180c7775e6))
2023-07-14 08:39:40 +00:00
LisoUseInAIKyrios
180c7775e6 fix(youtube/sponsorblock): fix some segments skipping slightly too late (#2634) 2023-07-14 12:35:49 +04:00
semantic-release-bot
d0440c17f6 chore(release): 2.184.0 [skip ci]
# [2.184.0](https://github.com/revanced/revanced-patches/compare/v2.183.1...v2.184.0) (2023-07-11)

### Features

* **youtube/custom-branding:** update logo ([801584b](801584b78c))
2023-07-11 00:56:29 +00:00
oSumAtrIX
c6f4497031 chore: merge branch dev to main (#2615) 2023-07-11 02:54:05 +02:00
semantic-release-bot
20f24513d5 chore(release): 2.184.0-dev.1 [skip ci]
# [2.184.0-dev.1](https://github.com/revanced/revanced-patches/compare/v2.183.1...v2.184.0-dev.1) (2023-07-11)

### Features

* **youtube/custom-branding:** update logo ([801584b](801584b78c))
2023-07-11 00:48:58 +00:00
oSumAtrIX
db2fd097f6 refactor: remove unnecessary annotations 2023-07-11 02:45:56 +02:00
oSumAtrIX
801584b78c feat(youtube/custom-branding): update logo 2023-07-11 02:45:15 +02:00
87 changed files with 528 additions and 639 deletions

View File

@@ -1,3 +1,117 @@
# [2.186.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v2.186.0-dev.2...v2.186.0-dev.3) (2023-07-20)
### Bug Fixes
* **Tiktok - Settings:** get instruction registers dynamically ([#2676](https://github.com/ReVanced/revanced-patches/issues/2676)) ([b34e45b](https://github.com/ReVanced/revanced-patches/commit/b34e45b6dafad8e9d567ad65f58a182b8cc04676))
# [2.186.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.186.0-dev.1...v2.186.0-dev.2) (2023-07-20)
### Bug Fixes
* **YouTube - Theme:** apply custom seekbar color to shorts ([#2670](https://github.com/ReVanced/revanced-patches/issues/2670)) ([1f6fe3d](https://github.com/ReVanced/revanced-patches/commit/1f6fe3da4284fd768057ef068c7ddf88d3a11049))
### Features
* **Youtube - Theme:** add a switch to enable/disable custom seekbar color ([#2663](https://github.com/ReVanced/revanced-patches/issues/2663)) ([5c39985](https://github.com/ReVanced/revanced-patches/commit/5c39985888cdfe3acfdd8811ff9b6f80e243704e))
# [2.186.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v2.185.0...v2.186.0-dev.1) (2023-07-20)
### Features
* **Twitter:** remove `Hide view stats` patch ([f0d3800](https://github.com/ReVanced/revanced-patches/commit/f0d38001b34db63f212209afb91eebf59dad2b24))
# [2.185.0](https://github.com/ReVanced/revanced-patches/compare/v2.184.0...v2.185.0) (2023-07-20)
### Bug Fixes
* allocate for more than eight `LithoFilter` array items ([#2643](https://github.com/ReVanced/revanced-patches/issues/2643)) ([fc8660b](https://github.com/ReVanced/revanced-patches/commit/fc8660b740bec2747e5f82b7321027bb8a51e0cf))
* **Sync for Reddit - Disable ads:** fix compatibility with latest version ([1456577](https://github.com/ReVanced/revanced-patches/commit/1456577f11c4a7e49d6c1ba0103b919dc487f4cf))
* **Tiktok - Settings:** bump compatibility ([#2656](https://github.com/ReVanced/revanced-patches/issues/2656)) ([6641356](https://github.com/ReVanced/revanced-patches/commit/6641356d41813a20c77faac67c37ea517690d25b))
* **TikTok - Show seekbar:** fix seekbar not always showing ([#2660](https://github.com/ReVanced/revanced-patches/issues/2660)) ([f2742f1](https://github.com/ReVanced/revanced-patches/commit/f2742f1ba117809971a10780823fca99c19a4f34))
* **Trakt - Unlock pro:** constraint to last known working version ([#2662](https://github.com/ReVanced/revanced-patches/issues/2662)) ([324bbde](https://github.com/ReVanced/revanced-patches/commit/324bbde92a851e855c11f266e92fa14c39d88160))
* **YouTube - Spoof client:** show video time and chapters while using seekbar ([#2607](https://github.com/ReVanced/revanced-patches/issues/2607)) ([9546d12](https://github.com/ReVanced/revanced-patches/commit/9546d126430870d1abd8f43bb687b31b9fcb6fb5))
* **youtube/sponsorblock:** fix some segments skipping slightly too late ([#2634](https://github.com/ReVanced/revanced-patches/issues/2634)) ([3175431](https://github.com/ReVanced/revanced-patches/commit/31754311870324b1e245b12965d7486878e9eba4))
### Features
* **youtube:** rename `video-speed` to `playback-speed` ([#2642](https://github.com/ReVanced/revanced-patches/issues/2642)) ([77e8639](https://github.com/ReVanced/revanced-patches/commit/77e8639b71048f2795f8f32fe18d052b335e3ce4))
# [2.185.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v2.185.0-dev.6...v2.185.0-dev.7) (2023-07-19)
### Bug Fixes
* **YouTube - Spoof client:** show video time and chapters while using seekbar ([#2607](https://github.com/ReVanced/revanced-patches/issues/2607)) ([9546d12](https://github.com/ReVanced/revanced-patches/commit/9546d126430870d1abd8f43bb687b31b9fcb6fb5))
# [2.185.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v2.185.0-dev.5...v2.185.0-dev.6) (2023-07-19)
### Bug Fixes
* **Tiktok - Settings:** bump compatibility ([#2656](https://github.com/ReVanced/revanced-patches/issues/2656)) ([6641356](https://github.com/ReVanced/revanced-patches/commit/6641356d41813a20c77faac67c37ea517690d25b))
# [2.185.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v2.185.0-dev.4...v2.185.0-dev.5) (2023-07-19)
### Bug Fixes
* **Trakt - Unlock pro:** constraint to last known working version ([#2662](https://github.com/ReVanced/revanced-patches/issues/2662)) ([324bbde](https://github.com/ReVanced/revanced-patches/commit/324bbde92a851e855c11f266e92fa14c39d88160))
# [2.185.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v2.185.0-dev.3...v2.185.0-dev.4) (2023-07-19)
### Bug Fixes
* **TikTok - Show seekbar:** fix seekbar not always showing ([#2660](https://github.com/ReVanced/revanced-patches/issues/2660)) ([f2742f1](https://github.com/ReVanced/revanced-patches/commit/f2742f1ba117809971a10780823fca99c19a4f34))
# [2.185.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v2.185.0-dev.2...v2.185.0-dev.3) (2023-07-17)
### Bug Fixes
* **Sync for Reddit - Disable ads:** fix compatibility with latest version ([1456577](https://github.com/ReVanced/revanced-patches/commit/1456577f11c4a7e49d6c1ba0103b919dc487f4cf))
# [2.185.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.185.0-dev.1...v2.185.0-dev.2) (2023-07-15)
### Bug Fixes
* allocate for more than eight `LithoFilter` array items ([#2643](https://github.com/ReVanced/revanced-patches/issues/2643)) ([fc8660b](https://github.com/ReVanced/revanced-patches/commit/fc8660b740bec2747e5f82b7321027bb8a51e0cf))
# [2.185.0-dev.1](https://github.com/revanced/revanced-patches/compare/v2.184.1-dev.1...v2.185.0-dev.1) (2023-07-15)
### Features
* **youtube:** rename `video-speed` to `playback-speed` ([#2642](https://github.com/revanced/revanced-patches/issues/2642)) ([77e8639](https://github.com/revanced/revanced-patches/commit/77e8639b71048f2795f8f32fe18d052b335e3ce4))
## [2.184.1-dev.1](https://github.com/revanced/revanced-patches/compare/v2.184.0...v2.184.1-dev.1) (2023-07-14)
### Bug Fixes
* **youtube/sponsorblock:** fix some segments skipping slightly too late ([#2634](https://github.com/revanced/revanced-patches/issues/2634)) ([3175431](https://github.com/revanced/revanced-patches/commit/31754311870324b1e245b12965d7486878e9eba4))
# [2.184.0](https://github.com/revanced/revanced-patches/compare/v2.183.1...v2.184.0) (2023-07-11)
### Features
* **youtube/custom-branding:** update logo ([e2187f3](https://github.com/revanced/revanced-patches/commit/e2187f33ff82fce40592517aef31cb191b42987c))
# [2.184.0-dev.1](https://github.com/revanced/revanced-patches/compare/v2.183.1...v2.184.0-dev.1) (2023-07-11)
### Features
* **youtube/custom-branding:** update logo ([e2187f3](https://github.com/revanced/revanced-patches/commit/e2187f33ff82fce40592517aef31cb191b42987c))
## [2.183.1](https://github.com/revanced/revanced-patches/compare/v2.183.0...v2.183.1) (2023-07-10) ## [2.183.1](https://github.com/revanced/revanced-patches/compare/v2.183.0...v2.183.1) (2023-07-10)

View File

@@ -1,4 +1,4 @@
org.gradle.parallel = true org.gradle.parallel = true
org.gradle.caching = true org.gradle.caching = true
kotlin.code.style = official kotlin.code.style = official
version = 2.183.1 version = 2.186.0-dev.3

File diff suppressed because one or more lines are too long

View File

@@ -1,17 +1,13 @@
package app.revanced.patches.all.screencapture.removerestriction.resource.patch package app.revanced.patches.all.screencapture.removerestriction.resource.patch
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch import app.revanced.patcher.patch.ResourcePatch
import org.w3c.dom.Element import org.w3c.dom.Element
@Name("Remove screen capture restriction resource patch")
@Description("Sets allowAudioPlaybackCapture in manifest to true.") @Description("Sets allowAudioPlaybackCapture in manifest to true.")
@Version("0.0.1")
internal class RemoveCaptureRestrictionResourcePatch : ResourcePatch { internal class RemoveCaptureRestrictionResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult { override fun execute(context: ResourceContext): PatchResult {
// create an xml editor instance // create an xml editor instance

View File

@@ -1,13 +1,10 @@
package app.revanced.patches.music.misc.microg.patch.resource package app.revanced.patches.music.misc.microg.patch.resource
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patches.music.annotations.MusicCompatibility
import app.revanced.patches.music.misc.microg.shared.Constants.MUSIC_PACKAGE_NAME import app.revanced.patches.music.misc.microg.shared.Constants.MUSIC_PACKAGE_NAME
import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_APP_NAME import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_APP_NAME
import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_PACKAGE_NAME import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_PACKAGE_NAME
@@ -16,10 +13,7 @@ import app.revanced.patches.music.misc.microg.shared.Constants.SPOOFED_PACKAGE_S
import app.revanced.util.microg.MicroGManifestHelper import app.revanced.util.microg.MicroGManifestHelper
import app.revanced.util.microg.MicroGResourceHelper import app.revanced.util.microg.MicroGResourceHelper
@Name("Vanced MicroG resource patch")
@Description("Resource patch to allow YouTube Music ReVanced to run without root and under a different package name.") @Description("Resource patch to allow YouTube Music ReVanced to run without root and under a different package name.")
@MusicCompatibility
@Version("0.0.2")
class MicroGResourcePatch : ResourcePatch { class MicroGResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult { override fun execute(context: ResourceContext): PatchResult {
// update manifest // update manifest

View File

@@ -1,11 +1,10 @@
package app.revanced.patches.syncforreddit.detection.piracy.fingerprints package app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.ReferenceInstruction import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.reference.TypeReference
object PiracyDetectionFingerprint : MethodFingerprint( object PiracyDetectionFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",

View File

@@ -1,19 +1,18 @@
package app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.patch package app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patches.syncforreddit.detection.piracy.fingerprints.PiracyDetectionFingerprint import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.fingerprints.PiracyDetectionFingerprint
@Description("Disables detection of modified versions.") @Description("Disables detection of modified versions.")
@Version("0.0.1")
class DisablePiracyDetectionPatch : BytecodePatch(listOf(PiracyDetectionFingerprint)) { class DisablePiracyDetectionPatch : BytecodePatch(listOf(PiracyDetectionFingerprint)) {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
// Do not return an error if the fingerprint is not resolved.
// This is fine because new versions of the target app do not need this patch.
PiracyDetectionFingerprint.result?.mutableMethod?.apply { PiracyDetectionFingerprint.result?.mutableMethod?.apply {
addInstruction( addInstruction(
0, 0,
@@ -21,7 +20,7 @@ class DisablePiracyDetectionPatch : BytecodePatch(listOf(PiracyDetectionFingerpr
return-void return-void
""" """
) )
} ?: return PiracyDetectionFingerprint.toErrorResult() }
return PatchResultSuccess() return PatchResultSuccess()
} }

View File

@@ -1,8 +1,5 @@
package app.revanced.patches.shared.mapping.misc.patch package app.revanced.patches.shared.mapping.misc.patch
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
@@ -13,9 +10,6 @@ import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@Name("Resource mapping")
@Description("Creates a map of public resources.")
@Version("0.0.1")
class ResourceMappingPatch : ResourcePatch { class ResourceMappingPatch : ResourcePatch {
companion object { companion object {
internal lateinit var resourceMappings: List<ResourceElement> internal lateinit var resourceMappings: List<ResourceElement>

View File

@@ -1,12 +0,0 @@
package app.revanced.patches.tiktok.interaction.seekbar.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
object AwemeGetVideoControlFingerprint : MethodFingerprint(
"L",
AccessFlags.PUBLIC.value,
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/Aweme;") && methodDef.name == "getVideoControl"
}
)

View File

@@ -0,0 +1,9 @@
package app.revanced.patches.tiktok.interaction.seekbar.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object SetSeekBarShowTypeFingerprint : MethodFingerprint(
strings = listOf(
"seekbar show type change, change to:"
),
)

View File

@@ -6,17 +6,14 @@ import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.tiktok.interaction.seekbar.annotations.ShowSeekbarCompatibility import app.revanced.patches.tiktok.interaction.seekbar.annotations.ShowSeekbarCompatibility
import app.revanced.patches.tiktok.interaction.seekbar.fingerprints.AwemeGetVideoControlFingerprint import app.revanced.patches.tiktok.interaction.seekbar.fingerprints.SetSeekBarShowTypeFingerprint
import org.jf.dexlib2.Opcode import org.jf.dexlib2.iface.instruction.formats.Instruction22t
import org.jf.dexlib2.builder.instruction.BuilderInstruction11n
import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
import org.jf.dexlib2.builder.instruction.BuilderInstruction22c
@Patch @Patch
@Name("Show seekbar") @Name("Show seekbar")
@@ -25,27 +22,20 @@ import org.jf.dexlib2.builder.instruction.BuilderInstruction22c
@Version("0.0.1") @Version("0.0.1")
class ShowSeekbarPatch : BytecodePatch( class ShowSeekbarPatch : BytecodePatch(
listOf( listOf(
AwemeGetVideoControlFingerprint SetSeekBarShowTypeFingerprint,
) )
) { ) {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
//Get VideoControl FieldReference SetSeekBarShowTypeFingerprint.result?.mutableMethod?.apply {
val videoControl = context.findClass { it.type.endsWith("/VideoControl;") } val typeRegister = getInstruction<Instruction22t>(1).registerB
?: return PatchResultError("Can not find target class")
val fieldList = videoControl.immutableClass.fields.associateBy { field -> field.name }
AwemeGetVideoControlFingerprint.result?.mutableMethod?.implementation?.apply {
val ifNullLabel = newLabelForIndex(1)
addInstructions( addInstructions(
1, 0,
listOf( """
BuilderInstruction11n(Opcode.CONST_4, 1, 1), const/16 v$typeRegister, 0x64
BuilderInstruction21t(Opcode.IF_EQZ, 0, ifNullLabel), """
BuilderInstruction22c(Opcode.IPUT, 1, 0, fieldList["showProgressBar"]!!),
BuilderInstruction22c(Opcode.IPUT, 1, 0, fieldList["draftProgressBar"]!!)
)
) )
} ?: return AwemeGetVideoControlFingerprint.toErrorResult() } ?: return SetSeekBarShowTypeFingerprint.toErrorResult()
return PatchResultSuccess() return PatchResultSuccess()
} }

View File

@@ -1,17 +0,0 @@
package app.revanced.patches.tiktok.misc.settings.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode
object AboutPageFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.CONST, // copyrightPolicyLabel resource id
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING
),
customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lcom/ss/android/ugc/aweme/setting/page/AboutPage;" &&
methodDef.name == "onViewCreated"
}
)

View File

@@ -0,0 +1,22 @@
package app.revanced.patches.tiktok.misc.settings.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode
object AddSettingsEntryFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.CONST_CLASS,
Opcode.APUT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
),
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/SettingNewVersionFragment;") &&
methodDef.name == "onViewCreated"
}
)

View File

@@ -0,0 +1,9 @@
package app.revanced.patches.tiktok.misc.settings.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object SettingsEntryFingerprint : MethodFingerprint(
strings = listOf(
"pls pass item or extends the EventUnit"
)
)

View File

@@ -0,0 +1,10 @@
package app.revanced.patches.tiktok.misc.settings.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object SettingsEntryInfoFingerprint : MethodFingerprint(
strings = listOf(
"ExposeItem(title=",
", icon="
)
)

View File

@@ -1,10 +0,0 @@
package app.revanced.patches.tiktok.misc.settings.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object SettingsOnViewCreatedFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/SettingNewVersionFragment;") &&
methodDef.name == "onViewCreated"
}
)

View File

@@ -6,24 +6,20 @@ import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions 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.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.tiktok.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.tiktok.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.tiktok.misc.settings.annotations.SettingsCompatibility import app.revanced.patches.tiktok.misc.settings.annotations.SettingsCompatibility
import app.revanced.patches.tiktok.misc.settings.fingerprints.AboutPageFingerprint import app.revanced.patches.tiktok.misc.settings.fingerprints.*
import app.revanced.patches.tiktok.misc.settings.fingerprints.AdPersonalizationActivityOnCreateFingerprint
import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsOnViewCreatedFingerprint
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction import org.jf.dexlib2.iface.instruction.formats.Instruction35c
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
@Patch @Patch
@DependsOn([IntegrationsPatch::class]) @DependsOn([IntegrationsPatch::class])
@@ -33,65 +29,46 @@ import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
@Version("0.0.1") @Version("0.0.1")
class SettingsPatch : BytecodePatch( class SettingsPatch : BytecodePatch(
listOf( listOf(
AboutPageFingerprint,
AdPersonalizationActivityOnCreateFingerprint, AdPersonalizationActivityOnCreateFingerprint,
SettingsOnViewCreatedFingerprint, AddSettingsEntryFingerprint,
SettingsEntryFingerprint,
SettingsEntryInfoFingerprint,
) )
) { ) {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
SettingsOnViewCreatedFingerprint.result?.mutableMethod?.apply { // Find the class name of classes which construct a settings entry
val instructions = implementation!!.instructions val settingsButtonClass = SettingsEntryFingerprint.result?.classDef?.type?.toClassName()
?: return SettingsEntryFingerprint.toErrorResult()
val settingsButtonInfoClass = SettingsEntryInfoFingerprint.result?.classDef?.type?.toClassName()
?: return SettingsEntryInfoFingerprint.toErrorResult()
// Find the indices that need to be patched. // Create a settings entry for 'revanced settings' and add it to settings fragment
val copyrightPolicyLabelId = AboutPageFingerprint.result?.let { AddSettingsEntryFingerprint.result?.apply {
val startIndex = it.scanResult.patternScanResult!!.startIndex scanResult.patternScanResult?.startIndex?.let {
it.mutableMethod.getInstruction<WideLiteralInstruction>(startIndex).wideLiteral val settingsEntries = mutableMethod.getInstruction(it + 3)
} ?: return AboutPageFingerprint.toErrorResult() val addEntry = mutableMethod.getInstruction<BuilderInstruction35c>(it + 5)
val register1 = addEntry.registerC
val copyrightIndex = instructions.indexOfFirst { val register2 = addEntry.registerD
(it as? ReferenceInstruction)?.reference.toString() == "copyright_policy" // Add the settings entry created to the settings fragment
} - 6 mutableMethod.addInstructions(
it + 6,
listOf(
// fixme: instead use Method.indexOfFirstConstantInstructionValue() settingsEntries,
val copyrightPolicyIndex = instructions.indexOfFirst { addEntry
(it as? WideLiteralInstruction)?.wideLiteral == copyrightPolicyLabelId )
} + 2
// Replace an existing settings entry with ReVanced settings entry.
arrayOf(
copyrightIndex,
copyrightPolicyIndex
).forEach { index ->
val instruction = getInstruction(index)
if (instruction.opcode != Opcode.MOVE_RESULT_OBJECT)
return PatchResultError("Hardcoded offset changed.")
val settingsEntryStringRegister = (instruction as OneRegisterInstruction).registerA
// Replace the settings entry string with a custom one.
replaceInstruction(
index,
"""
const-string v$settingsEntryStringRegister, "ReVanced Settings"
"""
) )
// These instructions call a method that create a settings entry use reflection base on the class name of classes that construct settings entry
// Replace the OnClickListener class with a custom one. mutableMethod.addInstructions(
val onClickListener = getInstruction<ReferenceInstruction>(index + 4).reference.toString() it + 6,
context.findClass(onClickListener)?.mutableClass?.methods?.first {
it.name == "onClick"
}?.addInstructions(
0,
""" """
invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->startSettingsActivity()V const-string v$register1, "$settingsButtonClass"
return-void const-string v$register2, "$settingsButtonInfoClass"
invoke-static {v$register1, v$register2}, $CREATE_SETTINGS_ENTRY_METHOD_DESCRIPTOR
move-result-object v$register2
""" """
) ?: return PatchResultError("Could not find the onClick method.") )
} }
} ?: return AddSettingsEntryFingerprint.toErrorResult()
} ?: return SettingsOnViewCreatedFingerprint.toErrorResult()
// Initialize the settings menu once the replaced setting entry is clicked. // Initialize the settings menu once the replaced setting entry is clicked.
AdPersonalizationActivityOnCreateFingerprint.result?.mutableMethod?.apply { AdPersonalizationActivityOnCreateFingerprint.result?.mutableMethod?.apply {
@@ -99,20 +76,28 @@ class SettingsPatch : BytecodePatch(
it.opcode == Opcode.INVOKE_SUPER it.opcode == Opcode.INVOKE_SUPER
} + 1 } + 1
val thisRegister = getInstruction<FiveRegisterInstruction>(initializeSettingsIndex - 1).registerC val thisRegister = getInstruction<Instruction35c>(initializeSettingsIndex - 1).registerC
val usableRegister = implementation!!.registerCount - parameters.size - 2
addInstructions( addInstructionsWithLabels(
initializeSettingsIndex, initializeSettingsIndex,
""" """
invoke-static {v$thisRegister}, $INITIALIZE_SETTINGS_METHOD_DESCRIPTOR invoke-static {v$thisRegister}, $INITIALIZE_SETTINGS_METHOD_DESCRIPTOR
move-result v$usableRegister
if-eqz v$usableRegister, :notrevanced
return-void return-void
""" """,
ExternalLabel("notrevanced", getInstruction(initializeSettingsIndex))
) )
} ?: return AdPersonalizationActivityOnCreateFingerprint.toErrorResult() } ?: return AdPersonalizationActivityOnCreateFingerprint.toErrorResult()
return PatchResultSuccess() return PatchResultSuccess()
} }
private fun String.toClassName(): String {
return substring(1, this.length - 1).replace("/", ".")
}
private companion object { private companion object {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/tiktok/settingsmenu/SettingsMenu;" "Lapp/revanced/tiktok/settingsmenu/SettingsMenu;"
@@ -120,6 +105,11 @@ class SettingsPatch : BytecodePatch(
private const val INITIALIZE_SETTINGS_METHOD_DESCRIPTOR = private const val INITIALIZE_SETTINGS_METHOD_DESCRIPTOR =
"$INTEGRATIONS_CLASS_DESCRIPTOR->initializeSettings(" + "$INTEGRATIONS_CLASS_DESCRIPTOR->initializeSettings(" +
"Lcom/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity;" + "Lcom/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity;" +
")V" ")Z"
private const val CREATE_SETTINGS_ENTRY_METHOD_DESCRIPTOR =
"$INTEGRATIONS_CLASS_DESCRIPTOR->createSettingsEntry(" +
"Ljava/lang/String;" +
"Ljava/lang/String;" +
")Ljava/lang/Object;"
} }
} }

View File

@@ -3,6 +3,6 @@ package app.revanced.patches.trakt.annotations
import app.revanced.patcher.annotation.Compatibility import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility([Package("tv.trakt.trakt")]) @Compatibility([Package("tv.trakt.trakt", arrayOf("1.1.1"))])
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)
internal annotation class UnlockProCompatibility internal annotation class UnlockProCompatibility

View File

@@ -1,15 +1,9 @@
package app.revanced.patches.twitch.misc.settings.resource.patch package app.revanced.patches.twitch.misc.settings.resource.patch
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patches.shared.settings.preference.impl.ArrayResource import app.revanced.patches.shared.settings.preference.impl.ArrayResource
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
import app.revanced.patches.shared.settings.resource.patch.AbstractSettingsResourcePatch import app.revanced.patches.shared.settings.resource.patch.AbstractSettingsResourcePatch
import app.revanced.patches.twitch.misc.settings.annotations.SettingsCompatibility
@Name("Settings resource patch")
@SettingsCompatibility
@Version("0.0.1")
class SettingsResourcePatch : AbstractSettingsResourcePatch( class SettingsResourcePatch : AbstractSettingsResourcePatch(
"revanced_prefs", "revanced_prefs",
"twitch/settings" "twitch/settings"

View File

@@ -1,12 +0,0 @@
package app.revanced.patches.twitter.layout.hideviews.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.twitter.android", arrayOf("9.69.1-release.0", "9.71.0-release.0")
)]
)
@Target(AnnotationTarget.CLASS)
internal annotation class HideViewsCompatibility

View File

@@ -1,15 +0,0 @@
package app.revanced.patches.twitter.layout.hideviews.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
object InlineActionTypesFingerprint : MethodFingerprint(
returnType = "Ljava/util/List",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
strings = listOf(
"getCurrentMemoizing()",
"android_animated_reply_icon_enabled",
"reply_voting_android_position_before_favorite_enabled"
)
)

View File

@@ -1,22 +0,0 @@
package app.revanced.patches.twitter.layout.hideviews.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
object TweetStatsContainerConstructorFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
parameters = listOf("L"),
opcodes = listOf(
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.CONST,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.CONST_4,
Opcode.INVOKE_VIRTUAL,
Opcode.INVOKE_VIRTUAL
)
)

View File

@@ -1,22 +0,0 @@
package app.revanced.patches.twitter.layout.hideviews.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
object TweetStatsContainerWrapperConstructorFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
parameters = listOf("L"),
opcodes = listOf(
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IPUT_OBJECT
)
)

View File

@@ -1,26 +0,0 @@
package app.revanced.patches.twitter.layout.hideviews.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
object TweetStatsViewDelegateBinderFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
opcodes = listOf(
Opcode.NEW_INSTANCE,
Opcode.CONST_16,
Opcode.INVOKE_DIRECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT,
Opcode.NEW_INSTANCE,
Opcode.CONST_16,
Opcode.INVOKE_DIRECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.RETURN_OBJECT
)
)

View File

@@ -1,114 +0,0 @@
package app.revanced.patches.twitter.layout.hideviews.patch
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
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.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.twitter.layout.hideviews.fingerprints.InlineActionTypesFingerprint
import app.revanced.patches.twitter.layout.hideviews.fingerprints.TweetStatsContainerConstructorFingerprint
import app.revanced.patches.twitter.layout.hideviews.fingerprints.TweetStatsContainerWrapperConstructorFingerprint
import app.revanced.patches.twitter.layout.hideviews.fingerprints.TweetStatsViewDelegateBinderFingerprint
import org.jf.dexlib2.Opcode
class HideViewsBytecodePatch : BytecodePatch(
listOf(
InlineActionTypesFingerprint,
TweetStatsContainerWrapperConstructorFingerprint,
TweetStatsContainerConstructorFingerprint,
TweetStatsViewDelegateBinderFingerprint
)
) {
override fun execute(context: BytecodeContext): PatchResult {
removeViewsFromTimeline(context)
removeTweetStatViewInitializer(context)
removeTweetStatViewWrapperInitializer(context)
removeViewDelegateBinderSubscription()
return PatchResultSuccess()
}
private fun removeViewsFromTimeline(context: BytecodeContext) {
val addViewsToActionBarMethodFingerprint = object : MethodFingerprint(
opcodes = listOf(
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.SGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.IF_EQZ,
)
) {}
transformMethodAtPattern(
context,
InlineActionTypesFingerprint,
addViewsToActionBarMethodFingerprint
) { patternScanResult, method ->
method.removeInstruction(patternScanResult.endIndex - 1)
}
}
private fun removeTweetStatViewInitializer(context: BytecodeContext) {
val returnFingerprint = object : MethodFingerprint(
opcodes = listOf(Opcode.RETURN_VOID)
) {}
transformMethodAtPattern(
context,
TweetStatsContainerConstructorFingerprint,
returnFingerprint
) { patternScanResult, method ->
method.removeInstructions(patternScanResult.endIndex - 3, 3)
}
}
private fun removeTweetStatViewWrapperInitializer(context: BytecodeContext) {
val wrapperReturnFingerprint = object : MethodFingerprint(
opcodes = listOf(
Opcode.IGET_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.RETURN_VOID,
)
) {}
transformMethodAtPattern(
context,
TweetStatsContainerWrapperConstructorFingerprint,
wrapperReturnFingerprint
) { patternScanResult, method ->
method.removeInstructions(patternScanResult.startIndex - 4, 4)
}
}
private fun removeViewDelegateBinderSubscription() {
transformMethod(TweetStatsViewDelegateBinderFingerprint) { result, method ->
method.removeInstructions(result.scanResult.patternScanResult!!.startIndex - 4, 10)
}
}
private fun transformMethodAtPattern(
context: BytecodeContext, methodFingerprint: MethodFingerprint,
patternFingerprint: MethodFingerprint, transformer: TransformerAtPattern
) {
transformMethod(methodFingerprint) { result, method ->
val patternResult = patternFingerprint.also {
it.resolve(context, method, result.classDef)
}.result!!
transformer(patternResult.scanResult.patternScanResult!!, method)
}
}
private fun transformMethod(methodFingerprint: MethodFingerprint, transformer: Transformer) {
val result = methodFingerprint.result!!
val method = result.mutableMethod
transformer(result, method)
}
}
private typealias Transformer = (MethodFingerprintResult, MutableMethod) -> Unit
private typealias TransformerAtPattern = (MethodFingerprintResult.MethodFingerprintScanResult.PatternScanResult, MutableMethod) -> Unit

View File

@@ -1,34 +0,0 @@
package app.revanced.patches.twitter.layout.hideviews.patch
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.twitter.layout.hideviews.annotations.HideViewsCompatibility
import org.w3c.dom.Element
@Patch
@DependsOn([HideViewsBytecodePatch::class])
@Name("Hide views stats")
@Description("Hides the view stats under tweets.")
@HideViewsCompatibility
@Version("0.0.1")
class HideViewsResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
arrayOf(
"res/layout/condensed_tweet_stats.xml",
"res/layout/focal_tweet_stats.xml"
).forEach { file ->
context.xmlEditor[file].use { editor ->
val tags = editor.file.getElementsByTagName("com.twitter.ui.tweet.TweetStatView")
List(tags.length) { tags.item(it) as Element }
.filter { it.getAttribute("android:id").contains("views_stat") }
.forEach { it.parentNode.removeChild(it) }
}
}
return PatchResultSuccess()
}
}

View File

@@ -1,7 +1,5 @@
package app.revanced.patches.youtube.interaction.copyvideourl.resource.patch package app.revanced.patches.youtube.interaction.copyvideourl.resource.patch
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
@@ -16,9 +14,7 @@ import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources import app.revanced.util.resources.ResourceUtils.copyResources
import app.revanced.util.resources.ResourceUtils.mergeStrings import app.revanced.util.resources.ResourceUtils.mergeStrings
@Name("Copy video url resource")
@DependsOn([BottomControlsResourcePatch::class, SettingsPatch::class]) @DependsOn([BottomControlsResourcePatch::class, SettingsPatch::class])
@Version("0.0.1")
class CopyVideoUrlResourcePatch : ResourcePatch { class CopyVideoUrlResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult { override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences( SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(

View File

@@ -1,7 +1,5 @@
package app.revanced.patches.youtube.interaction.downloads.resource.patch package app.revanced.patches.youtube.interaction.downloads.resource.patch
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
@@ -14,9 +12,7 @@ import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources import app.revanced.util.resources.ResourceUtils.copyResources
import app.revanced.util.resources.ResourceUtils.mergeStrings import app.revanced.util.resources.ResourceUtils.mergeStrings
@Name("External downloads resource patch")
@DependsOn([BottomControlsResourcePatch::class, SettingsPatch::class]) @DependsOn([BottomControlsResourcePatch::class, SettingsPatch::class])
@Version("0.0.1")
class ExternalDownloadsResourcePatch : ResourcePatch { class ExternalDownloadsResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult { override fun execute(context: ResourceContext): PatchResult {

View File

@@ -12,7 +12,6 @@ import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.util.resources.ResourceUtils import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources import app.revanced.util.resources.ResourceUtils.copyResources
@Name("Swipe controls resource patch")
@DependsOn([SettingsPatch::class]) @DependsOn([SettingsPatch::class])
@Version("0.0.1") @Version("0.0.1")
class SwipeControlsResourcePatch : ResourcePatch { class SwipeControlsResourcePatch : ResourcePatch {

View File

@@ -1,7 +1,5 @@
package app.revanced.patches.youtube.layout.hide.albumcards.resource.patch package app.revanced.patches.youtube.layout.hide.albumcards.resource.patch
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
@@ -10,13 +8,9 @@ import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.layout.hide.albumcards.annotations.AlbumCardsCompatibility
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
@Name("Hide album cards resource patch")
@AlbumCardsCompatibility
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class]) @DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
@Version("0.0.1")
class AlbumCardsResourcePatch : ResourcePatch { class AlbumCardsResourcePatch : ResourcePatch {
companion object { companion object {
internal var albumCardId: Long = -1 internal var albumCardId: Long = -1

View File

@@ -1,7 +1,5 @@
package app.revanced.patches.youtube.layout.hide.breakingnews.resource.patch package app.revanced.patches.youtube.layout.hide.breakingnews.resource.patch
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
@@ -12,9 +10,7 @@ import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
@Name("Breaking news shelf resource patch")
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class]) @DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
@Version("0.0.1")
class BreakingNewsResourcePatch : ResourcePatch { class BreakingNewsResourcePatch : ResourcePatch {
companion object { companion object {
internal var horizontalCardListId: Long = -1 internal var horizontalCardListId: Long = -1

View File

@@ -1,7 +1,5 @@
package app.revanced.patches.youtube.layout.hide.crowdfundingbox.resource.patch package app.revanced.patches.youtube.layout.hide.crowdfundingbox.resource.patch
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
@@ -10,13 +8,9 @@ import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.layout.hide.crowdfundingbox.annotations.CrowdfundingBoxCompatibility
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
@Name("Crowdfunding box resource patch")
@CrowdfundingBoxCompatibility
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class]) @DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
@Version("0.0.1")
class CrowdfundingBoxResourcePatch : ResourcePatch { class CrowdfundingBoxResourcePatch : ResourcePatch {
companion object { companion object {
internal var crowdfundingBoxId: Long = -1 internal var crowdfundingBoxId: Long = -1

View File

@@ -1,7 +1,5 @@
package app.revanced.patches.youtube.layout.hide.endscreencards.resource.patch package app.revanced.patches.youtube.layout.hide.endscreencards.resource.patch
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
@@ -10,13 +8,9 @@ import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.layout.hide.endscreencards.annotations.HideEndscreenCardsCompatibility
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
@Name("Hide endscreen cards resource patch")
@HideEndscreenCardsCompatibility
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class]) @DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
@Version("0.0.1")
class HideEndscreenCardsResourcePatch : ResourcePatch { class HideEndscreenCardsResourcePatch : ResourcePatch {
internal companion object { internal companion object {
var layoutCircle: Long = -1 var layoutCircle: Long = -1

View File

@@ -1,6 +1,5 @@
package app.revanced.patches.youtube.layout.hide.loadmorebutton.resource.patch package app.revanced.patches.youtube.layout.hide.loadmorebutton.resource.patch
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
@@ -9,12 +8,9 @@ import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.layout.hide.loadmorebutton.annotations.HideLoadMoreButtonCompatibility
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
@Name("Hide load more button resource patch")
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class]) @DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
@HideLoadMoreButtonCompatibility
class HideLoadMoreButtonResourcePatch : ResourcePatch { class HideLoadMoreButtonResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult { override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(

View File

@@ -1,7 +1,5 @@
package app.revanced.patches.youtube.layout.hide.personalinformation.resource.patch package app.revanced.patches.youtube.layout.hide.personalinformation.resource.patch
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
@@ -10,13 +8,9 @@ import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.layout.hide.personalinformation.annotations.HideEmailAddressCompatibility
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
@Name("Hide email address resource patch")
@HideEmailAddressCompatibility
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class]) @DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
@Version("0.0.1")
class HideEmailAddressResourcePatch : ResourcePatch { class HideEmailAddressResourcePatch : ResourcePatch {
companion object { companion object {
internal var accountSwitcherAccessibilityLabelId: Long = -1 internal var accountSwitcherAccessibilityLabelId: Long = -1

View File

@@ -8,13 +8,9 @@ import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.layout.hide.player.overlay.annotations.HidePlayerOverlayPatchCompatibility
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import jdk.jfr.Name
@Name("Hide player overlay resource patch")
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class]) @DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
@HidePlayerOverlayPatchCompatibility
class HidePlayerOverlayResourcePatch : ResourcePatch { class HidePlayerOverlayResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult { override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(

View File

@@ -39,7 +39,7 @@ import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
PlayerTypeHookPatch::class, PlayerTypeHookPatch::class,
] ]
) )
@Name("Return youtube dislike") @Name("Return YouTube Dislike")
@Description("Shows the dislike count of videos using the Return YouTube Dislike API.") @Description("Shows the dislike count of videos using the Return YouTube Dislike API.")
@ReturnYouTubeDislikeCompatibility @ReturnYouTubeDislikeCompatibility
@Version("0.0.1") @Version("0.0.1")

View File

@@ -1,8 +1,5 @@
package app.revanced.patches.youtube.layout.returnyoutubedislike.resource.patch package app.revanced.patches.youtube.layout.returnyoutubedislike.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.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
@@ -11,15 +8,10 @@ import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.Preference import app.revanced.patches.shared.settings.preference.impl.Preference
import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.util.resources.ResourceUtils.mergeStrings import app.revanced.util.resources.ResourceUtils.mergeStrings
@DependsOn([SettingsPatch::class]) @DependsOn([SettingsPatch::class])
@Name("Return youtube dislike resource patch")
@Description("Adds the preferences for Return YouTube Dislike.")
@ReturnYouTubeDislikeCompatibility
@Version("0.0.1")
class ReturnYouTubeDislikeResourcePatch : ResourcePatch { class ReturnYouTubeDislikeResourcePatch : ResourcePatch {
companion object { companion object {
internal var oldUIDislikeId: Long = -1 internal var oldUIDislikeId: Long = -1

View File

@@ -6,7 +6,7 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarColorResourcePatch import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarColorResourcePatch
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
object CreateDarkThemeSeekbarFingerprint : MethodFingerprint( object PlayerSeekbarColorFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
customFingerprint = { method, _ -> customFingerprint = { method, _ ->
method.containsConstantInstructionValue(SeekbarColorResourcePatch.inlineTimeBarColorizedBarPlayedColorDarkId) method.containsConstantInstructionValue(SeekbarColorResourcePatch.inlineTimeBarColorizedBarPlayedColorDarkId)

View File

@@ -0,0 +1,11 @@
package app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarColorResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import org.jf.dexlib2.AccessFlags
object ShortsSeekbarColorFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
literal = SeekbarColorResourcePatch.reelTimeBarPlayedColorId,
)

View File

@@ -14,8 +14,9 @@ import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.layout.seekbar.annotations.SeekbarColorCompatibility import app.revanced.patches.youtube.layout.seekbar.annotations.SeekbarColorCompatibility
import app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints.CreateDarkThemeSeekbarFingerprint import app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints.PlayerSeekbarColorFingerprint
import app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints.SetSeekbarClickedColorFingerprint import app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints.SetSeekbarClickedColorFingerprint
import app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints.ShortsSeekbarColorFingerprint
import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarColorResourcePatch import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarColorResourcePatch
import app.revanced.patches.youtube.layout.theme.bytecode.patch.LithoColorHookPatch import app.revanced.patches.youtube.layout.theme.bytecode.patch.LithoColorHookPatch
import app.revanced.patches.youtube.layout.theme.bytecode.patch.LithoColorHookPatch.Companion.lithoColorOverrideHook import app.revanced.patches.youtube.layout.theme.bytecode.patch.LithoColorHookPatch.Companion.lithoColorOverrideHook
@@ -28,30 +29,29 @@ import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
@SeekbarColorCompatibility @SeekbarColorCompatibility
@Version("0.0.1") @Version("0.0.1")
class SeekbarColorBytecodePatch : BytecodePatch( class SeekbarColorBytecodePatch : BytecodePatch(
listOf(CreateDarkThemeSeekbarFingerprint, SetSeekbarClickedColorFingerprint) listOf(PlayerSeekbarColorFingerprint, ShortsSeekbarColorFingerprint, SetSeekbarClickedColorFingerprint)
) { ) {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
CreateDarkThemeSeekbarFingerprint.result?.mutableMethod?.apply { fun MutableMethod.addColorChangeInstructions(resourceId: Long) {
var registerIndex = indexOfFirstConstantInstructionValue(SeekbarColorResourcePatch.inlineTimeBarColorizedBarPlayedColorDarkId) + 2 var registerIndex = indexOfFirstConstantInstructionValue(resourceId) + 2
var colorRegister = (getInstruction(registerIndex) as OneRegisterInstruction).registerA var colorRegister = getInstruction<OneRegisterInstruction>(registerIndex).registerA
addInstructions( addInstructions(
registerIndex + 1, registerIndex + 1,
""" """
invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getVideoPlayerSeekbarColor(I)I invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getVideoPlayerSeekbarColor(I)I
move-result v$colorRegister move-result v$colorRegister
""" """
) )
}
registerIndex = indexOfFirstConstantInstructionValue(SeekbarColorResourcePatch.inlineTimeBarPlayedNotHighlightedColorId) + 2
colorRegister = (getInstruction(registerIndex) as OneRegisterInstruction).registerA PlayerSeekbarColorFingerprint.result?.mutableMethod?.apply {
addInstructions( addColorChangeInstructions(SeekbarColorResourcePatch.inlineTimeBarColorizedBarPlayedColorDarkId)
registerIndex + 1, addColorChangeInstructions(SeekbarColorResourcePatch.inlineTimeBarPlayedNotHighlightedColorId)
""" } ?: return PlayerSeekbarColorFingerprint.toErrorResult()
invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getVideoPlayerSeekbarColor(I)I
move-result v$colorRegister ShortsSeekbarColorFingerprint.result?.mutableMethod?.apply {
""" addColorChangeInstructions(SeekbarColorResourcePatch.reelTimeBarPlayedColorId)
) } ?: return ShortsSeekbarColorFingerprint.toErrorResult()
} ?: return CreateDarkThemeSeekbarFingerprint.toErrorResult()
SetSeekbarClickedColorFingerprint.result?.let { result -> SetSeekbarClickedColorFingerprint.result?.let { result ->
result.mutableMethod.let { result.mutableMethod.let {
@@ -62,7 +62,7 @@ class SeekbarColorBytecodePatch : BytecodePatch(
.getMethod() as MutableMethod .getMethod() as MutableMethod
method.apply { method.apply {
val colorRegister = (method.getInstruction(0) as TwoRegisterInstruction).registerA val colorRegister = getInstruction<TwoRegisterInstruction>(0).registerA
addInstructions( addInstructions(
0, 0,
""" """

View File

@@ -9,17 +9,20 @@ import org.w3c.dom.Element
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class]) @DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
class SeekbarColorResourcePatch : ResourcePatch { class SeekbarColorResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
// Edit theme colors via bytecode.
// For that the resource id is used in a bytecode patch to change the color.
val seekbarErrorMessage = "Could not find seekbar resource" override fun execute(context: ResourceContext): PatchResult {
inlineTimeBarColorizedBarPlayedColorDarkId = ResourceMappingPatch.resourceMappings fun findColorResource(resourceName: String): Long {
.find { it.name == "inline_time_bar_colorized_bar_played_color_dark" }?.id return ResourceMappingPatch.resourceMappings
?: return PatchResultError(seekbarErrorMessage) .find { it.type == "color" && it.name == resourceName }?.id
inlineTimeBarPlayedNotHighlightedColorId = ResourceMappingPatch.resourceMappings ?: throw PatchResultError("Could not find color resource: $resourceName")
.find { it.name == "inline_time_bar_played_not_highlighted_color" }?.id }
?: return PatchResultError(seekbarErrorMessage)
reelTimeBarPlayedColorId =
findColorResource("reel_time_bar_played_color")
inlineTimeBarColorizedBarPlayedColorDarkId =
findColorResource("inline_time_bar_colorized_bar_played_color_dark")
inlineTimeBarPlayedNotHighlightedColorId =
findColorResource("inline_time_bar_played_not_highlighted_color")
// Edit the resume playback drawable and replace the progress bar with a custom drawable // Edit the resume playback drawable and replace the progress bar with a custom drawable
context.xmlEditor["res/drawable/resume_playback_progressbar_drawable.xml"].use { editor -> context.xmlEditor["res/drawable/resume_playback_progressbar_drawable.xml"].use { editor ->
@@ -39,6 +42,7 @@ class SeekbarColorResourcePatch : ResourcePatch {
} }
companion object { companion object {
internal var reelTimeBarPlayedColorId = -1L
internal var inlineTimeBarColorizedBarPlayedColorDarkId = -1L internal var inlineTimeBarColorizedBarPlayedColorDarkId = -1L
internal var inlineTimeBarPlayedNotHighlightedColorId = -1L internal var inlineTimeBarPlayedNotHighlightedColorId = -1L
} }

View File

@@ -1,7 +1,5 @@
package app.revanced.patches.youtube.layout.sponsorblock.resource.patch package app.revanced.patches.youtube.layout.sponsorblock.resource.patch
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
@@ -16,9 +14,7 @@ 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.mergeStrings import app.revanced.util.resources.ResourceUtils.mergeStrings
@Name("SponsorBlock resource patch")
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class]) @DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
@Version("0.0.1")
class SponsorBlockResourcePatch : ResourcePatch { class SponsorBlockResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult { override fun execute(context: ResourceContext): PatchResult {

View File

@@ -9,6 +9,7 @@ import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.InputType import app.revanced.patches.shared.settings.preference.impl.InputType
import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.shared.settings.preference.impl.TextPreference import app.revanced.patches.shared.settings.preference.impl.TextPreference
import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarPreferencesPatch import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarPreferencesPatch
import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.darkThemeBackgroundColor import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.darkThemeBackgroundColor
@@ -20,10 +21,16 @@ import org.w3c.dom.Element
class ThemeResourcePatch : ResourcePatch { class ThemeResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult { override fun execute(context: ResourceContext): PatchResult {
SeekbarPreferencesPatch.addPreferences( SeekbarPreferencesPatch.addPreferences(
SwitchPreference(
"revanced_seekbar_custom_color",
StringResource("revanced_seekbar_custom_color_title", "Enable custom seekbar color"),
StringResource("revanced_seekbar_custom_color_summary_on", "Custom seekbar color is shown"),
StringResource("revanced_seekbar_custom_color_summary_off", "Original seekbar color is shown")
),
TextPreference( TextPreference(
"revanced_seekbar_color", "revanced_seekbar_custom_color_value",
StringResource("revanced_seekbar_color_title", "Seekbar color"), StringResource("revanced_seekbar_custom_color_value_title", "Custom seekbar color"),
StringResource("revanced_seekbar_color_summary", "The color of the seekbar"), StringResource("revanced_seekbar_custom_color_value_summary", "The color of the seekbar"),
InputType.TEXT_CAP_CHARACTERS InputType.TEXT_CAP_CHARACTERS
) )
) )

View File

@@ -0,0 +1,27 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.misc.fix.playback.patch.SpoofSignatureVerificationResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
object ScrubbedPreviewLayoutFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
returnType = "V",
parameters = listOf("Landroid/content/Context;", "Landroid/util/AttributeSet;", "I", "I"),
opcodes = listOf(
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.INVOKE_VIRTUAL,
Opcode.CONST,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IPUT_OBJECT, // preview imageview
),
// This resource is used in ~ 40 different locations, but this method has a distinct list of parameters to match to.
literal = SpoofSignatureVerificationResourcePatch.scrubbedPreviewThumbnailResourceId
)

View File

@@ -0,0 +1,23 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
/**
* Resolves using the class found in [StoryboardThumbnailParentFingerprint].
*/
object StoryboardThumbnailFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "Z",
parameters = listOf(),
opcodes = listOf(
Opcode.MOVE_RESULT,
Opcode.IF_GTZ,
Opcode.GOTO,
Opcode.CONST_4,
Opcode.RETURN,
Opcode.RETURN, // Last instruction of method.
),
)

View File

@@ -0,0 +1,17 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
/**
* Here lies code that creates the seekbar thumbnails.
*
* An additional change here might force the thumbnails to be created,
* or possibly a change somewhere else (maybe involving YouTube 18.23.35 class `hte`)
*/
object StoryboardThumbnailParentFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "Landroid/graphics/Bitmap;",
strings = listOf("Storyboard regionDecoder.decodeRegion exception - "),
)

View File

@@ -1,6 +1,5 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode

View File

@@ -7,47 +7,35 @@ import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.data.toMethodWalker import app.revanced.patcher.data.toMethodWalker
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.youtube.misc.fix.playback.fingerprints.*
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.ProtobufParameterBuilderFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import org.jf.dexlib2.iface.instruction.ReferenceInstruction
@Name("Spoof signature verification") @Name("Spoof signature verification")
@Description("Spoofs a patched client to prevent playback issues.") @Description("Spoofs a patched client to prevent playback issues.")
@DependsOn([ @DependsOn([
SpoofSignatureVerificationResourcePatch::class,
IntegrationsPatch::class, IntegrationsPatch::class,
SettingsPatch::class, PlayerTypeHookPatch::class
PlayerTypeHookPatch::class,
]) ])
@Version("0.0.1") @Version("0.0.1")
class SpoofSignatureVerificationPatch : BytecodePatch( class SpoofSignatureVerificationPatch : BytecodePatch(
listOf( listOf(
ProtobufParameterBuilderFingerprint, ProtobufParameterBuilderFingerprint,
StoryboardThumbnailParentFingerprint,
ScrubbedPreviewLayoutFingerprint,
) )
) { ) {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
SettingsPatch.PreferenceScreen.MISC.addPreferences(
SwitchPreference(
"revanced_spoof_signature_verification",
StringResource("revanced_spoof_signature_verification_title", "Spoof app signature"),
StringResource("revanced_spoof_signature_verification_summary_on",
"App signature spoofed\\n\\n"
+ "Side effects include:\\n"
+ "• Ambient mode may not work\\n"
+ "• Seekbar thumbnails are hidden\\n"
+ "• Downloading videos may not work"),
StringResource("revanced_spoof_signature_verification_summary_off", "App signature not spoofed"),
StringResource("revanced_spoof_signature_verification_user_dialog_message",
"Turning off this setting may cause playback issues.")
)
)
// hook parameter // hook parameter
ProtobufParameterBuilderFingerprint.result?.let { ProtobufParameterBuilderFingerprint.result?.let {
@@ -68,6 +56,53 @@ class SpoofSignatureVerificationPatch : BytecodePatch(
} }
} ?: return ProtobufParameterBuilderFingerprint.toErrorResult() } ?: return ProtobufParameterBuilderFingerprint.toErrorResult()
// When signature spoofing is enabled, the seekbar when tapped does not show
// the video time, chapter names, or the video thumbnail.
// Changing the value returned of this method forces all of these to show up,
// except the thumbnails are blank, which is handled with the patch below.
StoryboardThumbnailParentFingerprint.result ?: return StoryboardThumbnailParentFingerprint.toErrorResult()
StoryboardThumbnailFingerprint.resolve(context, StoryboardThumbnailParentFingerprint.result!!.classDef)
StoryboardThumbnailFingerprint.result?.apply {
val endIndex = scanResult.patternScanResult!!.endIndex
// Replace existing instruction to preserve control flow label.
// The replaced return instruction always returns false
// (it is the 'no thumbnails found' control path),
// so there is no need to pass the existing return value to integrations.
mutableMethod.replaceInstruction(
endIndex,
"""
invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarThumbnailOverrideValue()Z
"""
)
// Since this is end of the method must replace one line then add the rest.
mutableMethod.addInstructions(
endIndex + 1,
"""
move-result v0
return v0
"""
)
} ?: return StoryboardThumbnailFingerprint.toErrorResult()
// Seekbar thumbnail now show up but are always a blank image.
// Additional changes are needed to force the client to generate the thumbnails (assuming it's possible),
// but for now hide the empty thumbnail.
ScrubbedPreviewLayoutFingerprint.result?.apply {
val endIndex = scanResult.patternScanResult!!.endIndex
mutableMethod.apply {
val imageViewFieldName = getInstruction<ReferenceInstruction>(endIndex).reference
addInstructions(
implementation!!.instructions.lastIndex,
"""
iget-object v0, p0, $imageViewFieldName # copy imageview field to a register
invoke-static {v0}, $INTEGRATIONS_CLASS_DESCRIPTOR->seekbarImageViewCreated(Landroid/widget/ImageView;)V
"""
)
}
} ?: return ScrubbedPreviewLayoutFingerprint.toErrorResult()
return PatchResultSuccess() return PatchResultSuccess()
} }

View File

@@ -0,0 +1,44 @@
package app.revanced.patches.youtube.misc.fix.playback.patch
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.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.*
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
class SpoofSignatureVerificationResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.PreferenceScreen.MISC.addPreferences(
SwitchPreference(
"revanced_spoof_signature_verification",
StringResource("revanced_spoof_signature_verification_title", "Spoof app signature"),
StringResource("revanced_spoof_signature_verification_summary_on",
"App signature spoofed\\n\\n"
+ "Side effects include:\\n"
+ "• Ambient mode may not work\\n"
+ "• Seekbar thumbnails are hidden\\n"
+ "• Downloading videos may not work"),
StringResource("revanced_spoof_signature_verification_summary_off", "App signature not spoofed"),
StringResource("revanced_spoof_signature_verification_user_dialog_message",
"Turning off this setting may cause playback issues.")
)
)
scrubbedPreviewThumbnailResourceId = ResourceMappingPatch.resourceMappings.single {
it.type == "id" && it.name == "thumbnail"
}.id
return PatchResultSuccess()
}
companion object {
var scrubbedPreviewThumbnailResourceId: Long = -1
}
}

View File

@@ -176,7 +176,7 @@ class LithoFilterPatch : BytecodePatch(
""" """
new-instance v1, $classDescriptor new-instance v1, $classDescriptor
invoke-direct {v1}, $classDescriptor-><init>()V invoke-direct {v1}, $classDescriptor-><init>()V
const/4 v2, ${filterCount++} const/16 v2, ${filterCount++}
aput-object v1, v0, v2 aput-object v1, v0, v2
""" """
) )
@@ -187,7 +187,7 @@ class LithoFilterPatch : BytecodePatch(
} }
override fun close() = LithoFilterFingerprint.result!! override fun close() = LithoFilterFingerprint.result!!
.mutableMethod.replaceInstruction(0, "const/4 v0, $filterCount") .mutableMethod.replaceInstruction(0, "const/16 v0, $filterCount")
companion object { companion object {
private val MethodFingerprint.patternScanResult private val MethodFingerprint.patternScanResult
@@ -208,4 +208,4 @@ class LithoFilterPatch : BytecodePatch(
private var filterCount = 0 private var filterCount = 0
} }
} }

View File

@@ -1,8 +1,5 @@
package app.revanced.patches.youtube.misc.microg.patch.resource package app.revanced.patches.youtube.misc.microg.patch.resource
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
@@ -10,7 +7,6 @@ import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.settings.preference.impl.Preference import app.revanced.patches.shared.settings.preference.impl.Preference
import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility
import app.revanced.patches.youtube.misc.microg.shared.Constants.PACKAGE_NAME import app.revanced.patches.youtube.misc.microg.shared.Constants.PACKAGE_NAME
import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_APP_NAME import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_APP_NAME
import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_PACKAGE_NAME import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_PACKAGE_NAME
@@ -22,11 +18,7 @@ import app.revanced.util.microg.Constants.MICROG_VENDOR
import app.revanced.util.microg.MicroGManifestHelper import app.revanced.util.microg.MicroGManifestHelper
import app.revanced.util.microg.MicroGResourceHelper import app.revanced.util.microg.MicroGResourceHelper
@Name("Vanced MicroG resource patch")
@DependsOn([SettingsResourcePatch::class]) @DependsOn([SettingsResourcePatch::class])
@Description("Resource patch to allow YouTube ReVanced to run without root and under a different package name.")
@MicroGPatchCompatibility
@Version("0.0.1")
class MicroGResourcePatch : ResourcePatch { class MicroGResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult { override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.addPreference( SettingsPatch.addPreference(

View File

@@ -1,8 +1,5 @@
package app.revanced.patches.youtube.misc.playercontrols.resource.patch 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.DomFileEditor import app.revanced.patcher.data.DomFileEditor
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
@@ -10,14 +7,9 @@ import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.youtube.misc.playercontrols.annotation.PlayerControlsCompatibility
import java.io.Closeable import java.io.Closeable
@Name("Bottom controls resource patch")
@Description("Manages the resources for the bottom controls of the YouTube player.")
@PlayerControlsCompatibility
@DependsOn([ResourceMappingPatch::class]) @DependsOn([ResourceMappingPatch::class])
@Version("0.0.1")
class BottomControlsResourcePatch : ResourcePatch, Closeable { class BottomControlsResourcePatch : ResourcePatch, Closeable {
override fun execute(context: ResourceContext): PatchResult { override fun execute(context: ResourceContext): PatchResult {
resourceContext = context resourceContext = context

View File

@@ -1,8 +1,5 @@
package app.revanced.patches.youtube.misc.settings.resource.patch package app.revanced.patches.youtube.misc.settings.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.DomFileEditor import app.revanced.patcher.data.DomFileEditor
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
@@ -19,10 +16,7 @@ import app.revanced.util.resources.ResourceUtils.mergeStrings
import org.w3c.dom.Element import org.w3c.dom.Element
import org.w3c.dom.Node import org.w3c.dom.Node
@Name("Settings resource patch")
@DependsOn([ResourceMappingPatch::class]) @DependsOn([ResourceMappingPatch::class])
@Description("Applies mandatory patches to implement ReVanced settings into the application.")
@Version("0.0.1")
class SettingsResourcePatch : AbstractSettingsResourcePatch( class SettingsResourcePatch : AbstractSettingsResourcePatch(
"revanced_prefs", "revanced_prefs",
"settings" "settings"

View File

@@ -21,7 +21,7 @@ import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
import org.jf.dexlib2.iface.reference.FieldReference import org.jf.dexlib2.iface.reference.FieldReference
@Patch @Patch
@Name("Hdr auto brightness") @Name("HDR auto brightness")
@Description("Makes the brightness of HDR videos follow the system default.") @Description("Makes the brightness of HDR videos follow the system default.")
@HDRBrightnessCompatibility @HDRBrightnessCompatibility
@Version("0.0.2") @Version("0.0.2")

View File

@@ -1,8 +0,0 @@
package app.revanced.patches.youtube.video.information.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object VideoTimeFingerprint : MethodFingerprint(
strings = listOf("MedialibPlayerTimeInfo{currentPositionMillis=")
)

View File

@@ -10,7 +10,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
@@ -44,7 +43,6 @@ class VideoInformationPatch : BytecodePatch(
PlayerInitFingerprint, PlayerInitFingerprint,
CreateVideoPlayerSeekbarFingerprint, CreateVideoPlayerSeekbarFingerprint,
PlayerControllerSetTimeReferenceFingerprint, PlayerControllerSetTimeReferenceFingerprint,
VideoTimeFingerprint,
OnPlaybackSpeedItemClickFingerprint, OnPlaybackSpeedItemClickFingerprint,
) )
) { ) {
@@ -118,18 +116,10 @@ class VideoInformationPatch : BytecodePatch(
.getMethod() as MutableMethod .getMethod() as MutableMethod
} }
/*
* Set the high precision video time method
*/
highPrecisionTimeMethod =
(object : MethodFingerprint("V", null, listOf("J", "J", "J", "J", "I", "L"), null) {}).also {
it.resolve(context, VideoTimeFingerprint.result!!.classDef)
}.result!!.mutableMethod
/* /*
* Hook the methods which set the time * Hook the methods which set the time
*/ */
highPrecisionTimeHook(INTEGRATIONS_CLASS_DESCRIPTOR, "setVideoTimeHighPrecision") videoTimeHook(INTEGRATIONS_CLASS_DESCRIPTOR, "setVideoTime")
/* /*
@@ -164,9 +154,6 @@ class VideoInformationPatch : BytecodePatch(
private lateinit var timeMethod: MutableMethod private lateinit var timeMethod: MutableMethod
private var timeInitInsertIndex = 2 private var timeInitInsertIndex = 2
private lateinit var highPrecisionTimeMethod: MutableMethod
private var highPrecisionInsertIndex = 0
private fun MutableMethod.insert(insertIndex: Int, register: String, descriptor: String) = private fun MutableMethod.insert(insertIndex: Int, register: String, descriptor: String) =
addInstruction(insertIndex, "invoke-static { $register }, $descriptor") addInstruction(insertIndex, "invoke-static { $register }, $descriptor")
@@ -202,20 +189,6 @@ class VideoInformationPatch : BytecodePatch(
"$targetMethodClass->$targetMethodName(J)V" "$targetMethodClass->$targetMethodName(J)V"
) )
/**
* Hook the high precision video time.
* The hooks is called extremely often (10 to 15 times a seconds), so use with caution.
* Note: the hook is usually called _off_ the main thread
*
* @param targetMethodClass The descriptor for the static method to invoke when the player controller is created.
* @param targetMethodName The name of the static method to invoke when the player controller is created.
*/
internal fun highPrecisionTimeHook(targetMethodClass: String, targetMethodName: String) =
highPrecisionTimeMethod.insertTimeHook(
highPrecisionInsertIndex++,
"$targetMethodClass->$targetMethodName(J)V"
)
private fun getReference(instructions: List<BuilderInstruction>, offset: Int, opcode: Opcode) = private fun getReference(instructions: List<BuilderInstruction>, offset: Int, opcode: Opcode) =
(instructions[instructions.indexOfFirst { it.opcode == opcode } + offset] as ReferenceInstruction) (instructions[instructions.indexOfFirst { it.opcode == opcode } + offset] as ReferenceInstruction)
.reference.toString() .reference.toString()

View File

@@ -1,25 +1,25 @@
package app.revanced.patches.youtube.video.speed package app.revanced.patches.youtube.video.speed
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
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.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.youtube.video.speed.custom.patch.CustomVideoSpeedPatch import app.revanced.patches.youtube.video.speed.custom.patch.CustomPlaybackSpeedPatch
import app.revanced.patches.youtube.video.speed.remember.patch.RememberPlaybackSpeedPatch import app.revanced.patches.youtube.video.speed.remember.patch.RememberPlaybackSpeedPatch
@Patch @Patch
@Name("Video speed") @Name("Playback speed")
@Description("Adds custom video speeds and ability to remember the playback speed you chose in the video playback speed flyout.") @Description("Adds custom playback speeds and ability to remember the playback speed you chose in the video playback speed flyout.")
@DependsOn([CustomVideoSpeedPatch::class, RememberPlaybackSpeedPatch::class]) @DependsOn([CustomPlaybackSpeedPatch::class, RememberPlaybackSpeedPatch::class])
@VideoSpeedCompatibility @PlaybackSpeedCompatibility
@Version("0.0.1") @Version("0.0.1")
class VideoSpeed : BytecodePatch() { class PlaybackSpeed : BytecodePatch() {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
return PatchResultSuccess() // All patches this patch depends on succeed. return PatchResultSuccess() // All patches this patch depends on succeed.
} }
} }

View File

@@ -5,4 +5,4 @@ import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.20.39", "18.23.35"))]) @Compatibility([Package("com.google.android.youtube", arrayOf("18.20.39", "18.23.35"))])
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)
internal annotation class VideoSpeedCompatibility internal annotation class PlaybackSpeedCompatibility

View File

@@ -2,7 +2,7 @@ package app.revanced.patches.youtube.video.speed.custom.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object GetOldVideoSpeedsFingerprint : MethodFingerprint( object GetOldPlaybackSpeedsFingerprint : MethodFingerprint(
parameters = listOf("[L", "I"), parameters = listOf("[L", "I"),
strings = listOf("menu_item_playback_speed") strings = listOf("menu_item_playback_speed")
) )

View File

@@ -2,6 +2,6 @@ package app.revanced.patches.youtube.video.speed.custom.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object ShowOldVideoSpeedMenuFingerprint : MethodFingerprint( object ShowOldPlaybackSpeedMenuFingerprint : MethodFingerprint(
strings = listOf("PLAYBACK_RATE_MENU_BOTTOM_SHEET_FRAGMENT") strings = listOf("PLAYBACK_RATE_MENU_BOTTOM_SHEET_FRAGMENT")
) )

View File

@@ -0,0 +1,7 @@
package app.revanced.patches.youtube.video.speed.custom.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object ShowOldPlaybackSpeedMenuIntegrationsFingerprint : MethodFingerprint(
customFingerprint = { method, _ -> method.name == "showOldPlaybackSpeedMenu" }
)

View File

@@ -1,7 +0,0 @@
package app.revanced.patches.youtube.video.speed.custom.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object ShowOldVideoSpeedMenuIntegrationsFingerprint : MethodFingerprint(
customFingerprint = { method, _ -> method.name == "showOldVideoSpeedMenu" }
)

View File

@@ -31,16 +31,16 @@ import org.jf.dexlib2.iface.reference.FieldReference
import org.jf.dexlib2.iface.reference.MethodReference import org.jf.dexlib2.iface.reference.MethodReference
import org.jf.dexlib2.immutable.ImmutableField import org.jf.dexlib2.immutable.ImmutableField
@Name("Custom video speed") @Name("Custom playback speed")
@Description("Adds custom video speed options.") @Description("Adds custom playback speed options.")
@DependsOn([IntegrationsPatch::class, LithoFilterPatch::class, SettingsPatch::class, BottomSheetHookPatch::class]) @DependsOn([IntegrationsPatch::class, LithoFilterPatch::class, SettingsPatch::class, BottomSheetHookPatch::class])
@Version("0.0.1") @Version("0.0.1")
class CustomVideoSpeedPatch : BytecodePatch( class CustomPlaybackSpeedPatch : BytecodePatch(
listOf( listOf(
SpeedArrayGeneratorFingerprint, SpeedArrayGeneratorFingerprint,
SpeedLimiterFingerprint, SpeedLimiterFingerprint,
GetOldVideoSpeedsFingerprint, GetOldPlaybackSpeedsFingerprint,
ShowOldVideoSpeedMenuIntegrationsFingerprint ShowOldPlaybackSpeedMenuIntegrationsFingerprint
) )
) { ) {
@@ -81,12 +81,12 @@ class CustomVideoSpeedPatch : BytecodePatch(
val arrayLengthConstDestination = (arrayLengthConst as OneRegisterInstruction).registerA val arrayLengthConstDestination = (arrayLengthConst as OneRegisterInstruction).registerA
val videoSpeedsArrayType = "$INTEGRATIONS_CLASS_DESCRIPTOR->customVideoSpeeds:[F" val playbackSpeedsArrayType = "$INTEGRATIONS_CLASS_DESCRIPTOR->customPlaybackSpeeds:[F"
arrayGenMethod.addInstructions( arrayGenMethod.addInstructions(
arrayLengthConstIndex + 1, arrayLengthConstIndex + 1,
""" """
sget-object v$arrayLengthConstDestination, $videoSpeedsArrayType sget-object v$arrayLengthConstDestination, $playbackSpeedsArrayType
array-length v$arrayLengthConstDestination, v$arrayLengthConstDestination array-length v$arrayLengthConstDestination, v$arrayLengthConstDestination
""" """
) )
@@ -102,7 +102,7 @@ class CustomVideoSpeedPatch : BytecodePatch(
arrayGenMethod.replaceInstruction( arrayGenMethod.replaceInstruction(
originalArrayFetchIndex, originalArrayFetchIndex,
"sget-object v$originalArrayFetchDestination, $videoSpeedsArrayType" "sget-object v$originalArrayFetchDestination, $playbackSpeedsArrayType"
) )
val limiterMethod = SpeedLimiterFingerprint.result?.mutableMethod!! val limiterMethod = SpeedLimiterFingerprint.result?.mutableMethod!!
@@ -121,24 +121,24 @@ class CustomVideoSpeedPatch : BytecodePatch(
// edit: alternatively this might work by overriding with fixed values such as 0.1x and 10x // edit: alternatively this might work by overriding with fixed values such as 0.1x and 10x
limiterMethod.replaceInstruction( limiterMethod.replaceInstruction(
limiterMinConstIndex, limiterMinConstIndex,
"sget v$limiterMinConstDestination, $INTEGRATIONS_CLASS_DESCRIPTOR->minVideoSpeed:F" "sget v$limiterMinConstDestination, $INTEGRATIONS_CLASS_DESCRIPTOR->minPlaybackSpeed:F"
) )
limiterMethod.replaceInstruction( limiterMethod.replaceInstruction(
limiterMaxConstIndex, limiterMaxConstIndex,
"sget v$limiterMaxConstDestination, $INTEGRATIONS_CLASS_DESCRIPTOR->maxVideoSpeed:F" "sget v$limiterMaxConstDestination, $INTEGRATIONS_CLASS_DESCRIPTOR->maxPlaybackSpeed:F"
) )
// region Force old video quality menu. // region Force old video quality menu.
// This is necessary, because there is no known way of adding custom video speeds to the new menu. // This is necessary, because there is no known way of adding custom playback speeds to the new menu.
BottomSheetHookPatch.addHook(INTEGRATIONS_CLASS_DESCRIPTOR) BottomSheetHookPatch.addHook(INTEGRATIONS_CLASS_DESCRIPTOR)
// Required to check if the video speed menu is currently shown. // Required to check if the playback speed menu is currently shown.
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR) LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
GetOldVideoSpeedsFingerprint.result?.let { result -> GetOldPlaybackSpeedsFingerprint.result?.let { result ->
// Add a static INSTANCE field to the class. // Add a static INSTANCE field to the class.
// This is later used to call "showOldVideoSpeedMenu" on the instance. // This is later used to call "showOldPlaybackSpeedMenu" on the instance.
val instanceField = ImmutableField( val instanceField = ImmutableField(
result.classDef.type, result.classDef.type,
"INSTANCE", "INSTANCE",
@@ -154,15 +154,15 @@ class CustomVideoSpeedPatch : BytecodePatch(
// In order to prevent a conflict with another patch, add the instruction at index 1. // In order to prevent a conflict with another patch, add the instruction at index 1.
result.mutableMethod.addInstruction(1, "sput-object p0, $instanceField") result.mutableMethod.addInstruction(1, "sput-object p0, $instanceField")
// Get the "showOldVideoSpeedMenu" method. // Get the "showOldPlaybackSpeedMenu" method.
// This is later called on the field INSTANCE. // This is later called on the field INSTANCE.
val showOldVideoSpeedMenuMethod = ShowOldVideoSpeedMenuFingerprint.also { val showOldPlaybackSpeedMenuMethod = ShowOldPlaybackSpeedMenuFingerprint.also {
if (!it.resolve(context, result.classDef)) if (!it.resolve(context, result.classDef))
throw ShowOldVideoSpeedMenuFingerprint.toErrorResult() throw ShowOldPlaybackSpeedMenuFingerprint.toErrorResult()
}.result!!.method.toString() }.result!!.method.toString()
// Insert the call to the "showOldVideoSpeedMenu" method on the field INSTANCE. // Insert the call to the "showOldPlaybackSpeedMenu" method on the field INSTANCE.
ShowOldVideoSpeedMenuIntegrationsFingerprint.result?.mutableMethod?.apply { ShowOldPlaybackSpeedMenuIntegrationsFingerprint.result?.mutableMethod?.apply {
addInstructionsWithLabels( addInstructionsWithLabels(
implementation!!.instructions.lastIndex, implementation!!.instructions.lastIndex,
""" """
@@ -170,11 +170,11 @@ class CustomVideoSpeedPatch : BytecodePatch(
if-nez v0, :not_null if-nez v0, :not_null
return-void return-void
:not_null :not_null
invoke-virtual { v0 }, $showOldVideoSpeedMenuMethod invoke-virtual { v0 }, $showOldPlaybackSpeedMenuMethod
""" """
) )
} ?: return ShowOldVideoSpeedMenuIntegrationsFingerprint.toErrorResult() } ?: return ShowOldPlaybackSpeedMenuIntegrationsFingerprint.toErrorResult()
} ?: return GetOldVideoSpeedsFingerprint.toErrorResult() } ?: return GetOldPlaybackSpeedsFingerprint.toErrorResult()
// endregion // endregion
@@ -183,10 +183,10 @@ class CustomVideoSpeedPatch : BytecodePatch(
private companion object { private companion object {
private const val FILTER_CLASS_DESCRIPTOR = private const val FILTER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/components/VideoSpeedMenuFilterPatch;" "Lapp/revanced/integrations/patches/components/PlaybackSpeedMenuFilterPatch;"
private const val INTEGRATIONS_CLASS_DESCRIPTOR = private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;" "Lapp/revanced/integrations/patches/playback/speed/CustomPlaybackSpeedPatch;"
} }
} }

View File

@@ -19,13 +19,13 @@ import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
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.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.video.information.patch.VideoInformationPatch import app.revanced.patches.youtube.video.information.patch.VideoInformationPatch
import app.revanced.patches.youtube.video.speed.custom.patch.CustomVideoSpeedPatch import app.revanced.patches.youtube.video.speed.custom.patch.CustomPlaybackSpeedPatch
import app.revanced.patches.youtube.video.speed.remember.fingerprint.InitializePlaybackSpeedValuesFingerprint import app.revanced.patches.youtube.video.speed.remember.fingerprint.InitializePlaybackSpeedValuesFingerprint
import org.jf.dexlib2.iface.instruction.ReferenceInstruction import org.jf.dexlib2.iface.instruction.ReferenceInstruction
@Name("Remember playback speed") @Name("Remember playback speed")
@Description("Adds the ability to remember the playback speed you chose in the video playback speed flyout.") @Description("Adds the ability to remember the playback speed you chose in the playback speed flyout.")
@DependsOn([IntegrationsPatch::class, SettingsPatch::class, VideoInformationPatch::class, CustomVideoSpeedPatch::class]) @DependsOn([IntegrationsPatch::class, SettingsPatch::class, VideoInformationPatch::class, CustomPlaybackSpeedPatch::class])
@Version("0.0.1") @Version("0.0.1")
class RememberPlaybackSpeedPatch : BytecodePatch( class RememberPlaybackSpeedPatch : BytecodePatch(
listOf( listOf(

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB