chore: Merge branch dev to main (#3232)

This commit is contained in:
oSumAtrIX 2023-11-18 05:10:32 +01:00 committed by GitHub
commit cd18216879
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
115 changed files with 1594 additions and 384 deletions

View file

@ -1,3 +1,247 @@
# [2.197.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v2.197.0-dev.4...v2.197.0-dev.5) (2023-11-18)
### Bug Fixes
* Use a checked cast by reifying the generic type parameter ([f7a296e](https://github.com/ReVanced/revanced-patches/commit/f7a296e1f17d7bfb5fd303ee83cabd8d625781b9))
### Features
* **YouTube - Client spoof:** Add description to preference screen ([843a568](https://github.com/ReVanced/revanced-patches/commit/843a56854465fe2052977cd2a8f24ecb839f8d2a))
* **YouTube - Hide layout components:** Add description to preference screen ([cc85441](https://github.com/ReVanced/revanced-patches/commit/cc854415e2311d4a06805a49a052fc8a16924739))
* **YouTube - Hide layout components:** Hide description components ([38b8e44](https://github.com/ReVanced/revanced-patches/commit/38b8e44ec494e7dea24066dc2f5af578e01d58dc))
* **YouTube - Navigation buttons:** Add description to preference screen ([14ea967](https://github.com/ReVanced/revanced-patches/commit/14ea9674c4e65ff2a92962222860b8035c7cda3f))
* **YouTube - Seekbar:** Add description to preference screen ([ea6de49](https://github.com/ReVanced/revanced-patches/commit/ea6de498e3b002feeabf72d20059090db0be7f94))
* **YouTube - Settings:** Sort preference screens below other types of preference ([9561db5](https://github.com/ReVanced/revanced-patches/commit/9561db50a82b0eeed07fe6541bc29a37f85b7caa))
* **YouTube:** Support version `18.45.41` ([7c4f021](https://github.com/ReVanced/revanced-patches/commit/7c4f021f8c849dfc448c18ffc800da39576be617))
# [2.197.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v2.197.0-dev.3...v2.197.0-dev.4) (2023-11-17)
### Features
* **YouTube - Return YouTube Dislike:** Support version `18.43.45` and `18.44.41` ([#3260](https://github.com/ReVanced/revanced-patches/issues/3260)) ([70dee58](https://github.com/ReVanced/revanced-patches/commit/70dee584ed91b8f3dc7fe63c3d77fef6ed1dc745))
# [2.197.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v2.197.0-dev.2...v2.197.0-dev.3) (2023-11-17)
### Features
* **Android Widgets (Material U):** Remove `Unlock paid widgets` patch ([#3286](https://github.com/ReVanced/revanced-patches/issues/3286)) ([b44da1c](https://github.com/ReVanced/revanced-patches/commit/b44da1c7018c88d30be0849569837b4e17c68e0f))
# [2.197.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.197.0-dev.1...v2.197.0-dev.2) (2023-11-17)
### Bug Fixes
* **YouTube - Disable resuming Shorts on startup:** Adjust patch name ([#3281](https://github.com/ReVanced/revanced-patches/issues/3281)) ([c332952](https://github.com/ReVanced/revanced-patches/commit/c3329527db739e6777fe8e77828e1226e4057b80))
* **YouTube - Hide layout components:** Reduce false positives when hiding mix playlists ([fb173e1](https://github.com/ReVanced/revanced-patches/commit/fb173e18afd5566a4ccdbb613810fa9646da9334))
### Features
* Add `Spoof SIM country` patch ([#3116](https://github.com/ReVanced/revanced-patches/issues/3116)) ([304a0d4](https://github.com/ReVanced/revanced-patches/commit/304a0d46bfee5ae96aaefee8f508eedd16004e36))
* **Facebook:** Add `Hide story ads` patch ([#3257](https://github.com/ReVanced/revanced-patches/issues/3257)) ([1408c2e](https://github.com/ReVanced/revanced-patches/commit/1408c2e6283f4c48020d4305008a45f53b96b5cc))
* **Twitch:** Support version `17.1.0` ([#3269](https://github.com/ReVanced/revanced-patches/issues/3269)) ([d88373b](https://github.com/ReVanced/revanced-patches/commit/d88373bf43a50198dec275301418435179bc822e))
* **YouTube - Bypass URL redirects:** Support version `18.43.45` ([e205ac7](https://github.com/ReVanced/revanced-patches/commit/e205ac761d836047c52a4862132b6ea7d5a10b1b))
* **YouTube - Hide timestamp:** Support version `18.43.45` ([9180d4f](https://github.com/ReVanced/revanced-patches/commit/9180d4f5c3d4a50f412b37af69d61aafce5ffc07))
* **YouTube - Navigation buttons:** Support version `18.43.45` ([e21286e](https://github.com/ReVanced/revanced-patches/commit/e21286e4d76323adb24ca8112a4ce03bfab98d60))
* **YouTube - Player flyout menu:** Support version `18.43.45` and `18.44.41` ([#3263](https://github.com/ReVanced/revanced-patches/issues/3263)) ([fcbebf9](https://github.com/ReVanced/revanced-patches/commit/fcbebf90f350cb7653e14da33b703eb25098dd55))
* **YouTube - Seekbar tapping:** Support version `18.43.45` ([eee51a8](https://github.com/ReVanced/revanced-patches/commit/eee51a863a059c5073b2817e57059e072b72155d))
* **YouTube - Vanced MicroG support:** Allow changing package name ([0c7490c](https://github.com/ReVanced/revanced-patches/commit/0c7490cbaf367d5029373096c41661c5112bfe53))
* **YouTube Music - Vanced MicroG support:** Allow changing package name ([ede2d67](https://github.com/ReVanced/revanced-patches/commit/ede2d67b921480fbe496b551e43b190836d6bb72))
* **YouTube:** Add `Enable slide to seek` patch ([68d10d4](https://github.com/ReVanced/revanced-patches/commit/68d10d4779d3545177fcf48f0aec237a2359b8b1))
* **YouTube:** Add `Remove tracking query parameter` patch ([ddda3f6](https://github.com/ReVanced/revanced-patches/commit/ddda3f6e8cd919edaa891baee6597d2566e18e50))
* **YouTube:** Bump compatibility to `18.38.45` ([9f19869](https://github.com/ReVanced/revanced-patches/commit/9f1986960cbaab84519d0685d1950764c16d08a5))
* **YouTube:** Bump compatibility to `18.44.41` ([384a0a6](https://github.com/ReVanced/revanced-patches/commit/384a0a67c52d7d342afae491388199aca6b78b4d))
* **YouTube:** Support version `18.43.45` for `Playback speed` and `Restore old video quality menu` ([c5236f8](https://github.com/ReVanced/revanced-patches/commit/c5236f812e1e362e4d03885b0950385e360bbff8))
# [2.197.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.197.0-dev.1...v2.197.0-dev.2) (2023-11-16)
### Bug Fixes
* **YouTube - Hide layout components:** Reduce false positives when hiding mix playlists ([fb173e1](https://github.com/ReVanced/revanced-patches/commit/fb173e18afd5566a4ccdbb613810fa9646da9334))
### Features
* Add `Spoof SIM country` patch ([#3116](https://github.com/ReVanced/revanced-patches/issues/3116)) ([304a0d4](https://github.com/ReVanced/revanced-patches/commit/304a0d46bfee5ae96aaefee8f508eedd16004e36))
* **Facebook:** Add `Hide story ads` patch ([#3257](https://github.com/ReVanced/revanced-patches/issues/3257)) ([1408c2e](https://github.com/ReVanced/revanced-patches/commit/1408c2e6283f4c48020d4305008a45f53b96b5cc))
* **Twitch:** Support version `17.1.0` ([#3269](https://github.com/ReVanced/revanced-patches/issues/3269)) ([d88373b](https://github.com/ReVanced/revanced-patches/commit/d88373bf43a50198dec275301418435179bc822e))
* **YouTube - Bypass URL redirects:** Support version `18.43.45` ([e205ac7](https://github.com/ReVanced/revanced-patches/commit/e205ac761d836047c52a4862132b6ea7d5a10b1b))
* **YouTube - Hide timestamp:** Support version `18.43.45` ([9180d4f](https://github.com/ReVanced/revanced-patches/commit/9180d4f5c3d4a50f412b37af69d61aafce5ffc07))
* **YouTube - Navigation buttons:** Support version `18.43.45` ([e21286e](https://github.com/ReVanced/revanced-patches/commit/e21286e4d76323adb24ca8112a4ce03bfab98d60))
* **YouTube - Player flyout menu:** Support version `18.43.45` and `18.44.41` ([#3263](https://github.com/ReVanced/revanced-patches/issues/3263)) ([fcbebf9](https://github.com/ReVanced/revanced-patches/commit/fcbebf90f350cb7653e14da33b703eb25098dd55))
* **YouTube - Seekbar tapping:** Support version `18.43.45` ([eee51a8](https://github.com/ReVanced/revanced-patches/commit/eee51a863a059c5073b2817e57059e072b72155d))
* **YouTube - Vanced MicroG support:** Allow changing package name ([0c7490c](https://github.com/ReVanced/revanced-patches/commit/0c7490cbaf367d5029373096c41661c5112bfe53))
* **YouTube Music - Vanced MicroG support:** Allow changing package name ([ede2d67](https://github.com/ReVanced/revanced-patches/commit/ede2d67b921480fbe496b551e43b190836d6bb72))
* **YouTube:** Add `Enable slide to seek` patch ([68d10d4](https://github.com/ReVanced/revanced-patches/commit/68d10d4779d3545177fcf48f0aec237a2359b8b1))
* **YouTube:** Add `Remove tracking query parameter` patch ([ddda3f6](https://github.com/ReVanced/revanced-patches/commit/ddda3f6e8cd919edaa891baee6597d2566e18e50))
* **YouTube:** Bump compatibility to `18.38.45` ([9f19869](https://github.com/ReVanced/revanced-patches/commit/9f1986960cbaab84519d0685d1950764c16d08a5))
* **YouTube:** Bump compatibility to `18.44.41` ([384a0a6](https://github.com/ReVanced/revanced-patches/commit/384a0a67c52d7d342afae491388199aca6b78b4d))
* **YouTube:** Support version `18.43.45` for `Playback speed` and `Restore old video quality menu` ([c5236f8](https://github.com/ReVanced/revanced-patches/commit/c5236f812e1e362e4d03885b0950385e360bbff8))
# [2.197.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.197.0-dev.1...v2.197.0-dev.2) (2023-11-15)
### Bug Fixes
* **YouTube - Hide layout components:** Reduce false positives when hiding mix playlists ([fb173e1](https://github.com/ReVanced/revanced-patches/commit/fb173e18afd5566a4ccdbb613810fa9646da9334))
### Features
* Add `Spoof SIM country` patch ([#3116](https://github.com/ReVanced/revanced-patches/issues/3116)) ([304a0d4](https://github.com/ReVanced/revanced-patches/commit/304a0d46bfee5ae96aaefee8f508eedd16004e36))
* **Facebook:** Add `Hide story ads` patch ([#3257](https://github.com/ReVanced/revanced-patches/issues/3257)) ([1408c2e](https://github.com/ReVanced/revanced-patches/commit/1408c2e6283f4c48020d4305008a45f53b96b5cc))
* **Twitch:** Support version `17.1.0` ([#3269](https://github.com/ReVanced/revanced-patches/issues/3269)) ([d88373b](https://github.com/ReVanced/revanced-patches/commit/d88373bf43a50198dec275301418435179bc822e))
* **YouTube - Bypass URL redirects:** Support version `18.43.45` ([e205ac7](https://github.com/ReVanced/revanced-patches/commit/e205ac761d836047c52a4862132b6ea7d5a10b1b))
* **YouTube - Hide timestamp:** Support version `18.43.45` ([9180d4f](https://github.com/ReVanced/revanced-patches/commit/9180d4f5c3d4a50f412b37af69d61aafce5ffc07))
* **YouTube - Navigation buttons:** Support version `18.43.45` ([e21286e](https://github.com/ReVanced/revanced-patches/commit/e21286e4d76323adb24ca8112a4ce03bfab98d60))
* **YouTube - Player flyout menu:** Support version `18.43.45` and `18.44.41` ([#3263](https://github.com/ReVanced/revanced-patches/issues/3263)) ([fcbebf9](https://github.com/ReVanced/revanced-patches/commit/fcbebf90f350cb7653e14da33b703eb25098dd55))
* **YouTube - Seekbar tapping:** Support version `18.43.45` ([eee51a8](https://github.com/ReVanced/revanced-patches/commit/eee51a863a059c5073b2817e57059e072b72155d))
* **YouTube:** Add `Enable slide to seek` patch ([68d10d4](https://github.com/ReVanced/revanced-patches/commit/68d10d4779d3545177fcf48f0aec237a2359b8b1))
* **YouTube:** Add `Remove tracking query parameter` patch ([ddda3f6](https://github.com/ReVanced/revanced-patches/commit/ddda3f6e8cd919edaa891baee6597d2566e18e50))
* **YouTube:** Bump compatibility to `18.38.45` ([9f19869](https://github.com/ReVanced/revanced-patches/commit/9f1986960cbaab84519d0685d1950764c16d08a5))
* **YouTube:** Bump compatibility to `18.44.41` ([384a0a6](https://github.com/ReVanced/revanced-patches/commit/384a0a67c52d7d342afae491388199aca6b78b4d))
* **YouTube:** Support version `18.43.45` for `Playback speed` and `Restore old video quality menu` ([c5236f8](https://github.com/ReVanced/revanced-patches/commit/c5236f812e1e362e4d03885b0950385e360bbff8))
# [2.197.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.197.0-dev.1...v2.197.0-dev.2) (2023-11-13)
### Bug Fixes
* **YouTube - Hide layout components:** Reduce false positives when hiding mix playlists ([fb173e1](https://github.com/ReVanced/revanced-patches/commit/fb173e18afd5566a4ccdbb613810fa9646da9334))
### Features
* Add `Spoof SIM country` patch ([#3116](https://github.com/ReVanced/revanced-patches/issues/3116)) ([304a0d4](https://github.com/ReVanced/revanced-patches/commit/304a0d46bfee5ae96aaefee8f508eedd16004e36))
* **Facebook:** Add `Hide story ads` patch ([#3257](https://github.com/ReVanced/revanced-patches/issues/3257)) ([1408c2e](https://github.com/ReVanced/revanced-patches/commit/1408c2e6283f4c48020d4305008a45f53b96b5cc))
* **YouTube - Bypass URL redirects:** Support version `18.43.45` ([e205ac7](https://github.com/ReVanced/revanced-patches/commit/e205ac761d836047c52a4862132b6ea7d5a10b1b))
* **YouTube - Hide timestamp:** Support version `18.43.45` ([9180d4f](https://github.com/ReVanced/revanced-patches/commit/9180d4f5c3d4a50f412b37af69d61aafce5ffc07))
* **YouTube - Navigation buttons:** Support version `18.43.45` ([e21286e](https://github.com/ReVanced/revanced-patches/commit/e21286e4d76323adb24ca8112a4ce03bfab98d60))
* **YouTube - Player flyout menu:** Support version `18.43.45` and `18.44.41` ([#3263](https://github.com/ReVanced/revanced-patches/issues/3263)) ([fcbebf9](https://github.com/ReVanced/revanced-patches/commit/fcbebf90f350cb7653e14da33b703eb25098dd55))
* **YouTube - Seekbar tapping:** Support version `18.43.45` ([eee51a8](https://github.com/ReVanced/revanced-patches/commit/eee51a863a059c5073b2817e57059e072b72155d))
* **YouTube:** Add `Enable slide to seek` patch ([68d10d4](https://github.com/ReVanced/revanced-patches/commit/68d10d4779d3545177fcf48f0aec237a2359b8b1))
* **YouTube:** Add `Remove tracking query parameter` patch ([ddda3f6](https://github.com/ReVanced/revanced-patches/commit/ddda3f6e8cd919edaa891baee6597d2566e18e50))
* **YouTube:** Bump compatibility to `18.38.45` ([9f19869](https://github.com/ReVanced/revanced-patches/commit/9f1986960cbaab84519d0685d1950764c16d08a5))
* **YouTube:** Bump compatibility to `18.44.41` ([384a0a6](https://github.com/ReVanced/revanced-patches/commit/384a0a67c52d7d342afae491388199aca6b78b4d))
* **YouTube:** Support version `18.43.45` for `Playback speed` and `Restore old video quality menu` ([c5236f8](https://github.com/ReVanced/revanced-patches/commit/c5236f812e1e362e4d03885b0950385e360bbff8))
# [2.197.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.197.0-dev.1...v2.197.0-dev.2) (2023-11-12)
### Bug Fixes
* **YouTube - Hide layout components:** Reduce false positives when hiding mix playlists ([fb173e1](https://github.com/ReVanced/revanced-patches/commit/fb173e18afd5566a4ccdbb613810fa9646da9334))
### Features
* Add `Spoof SIM country` patch ([#3116](https://github.com/ReVanced/revanced-patches/issues/3116)) ([304a0d4](https://github.com/ReVanced/revanced-patches/commit/304a0d46bfee5ae96aaefee8f508eedd16004e36))
* **Facebook:** Add `Hide story ads` patch ([#3257](https://github.com/ReVanced/revanced-patches/issues/3257)) ([1408c2e](https://github.com/ReVanced/revanced-patches/commit/1408c2e6283f4c48020d4305008a45f53b96b5cc))
* **YouTube - Bypass URL redirects:** Support version `18.43.45` ([e205ac7](https://github.com/ReVanced/revanced-patches/commit/e205ac761d836047c52a4862132b6ea7d5a10b1b))
* **YouTube - Hide timestamp:** Support version `18.43.45` ([9180d4f](https://github.com/ReVanced/revanced-patches/commit/9180d4f5c3d4a50f412b37af69d61aafce5ffc07))
* **YouTube - Navigation buttons:** Support version `18.43.45` ([e21286e](https://github.com/ReVanced/revanced-patches/commit/e21286e4d76323adb24ca8112a4ce03bfab98d60))
* **YouTube - Seekbar tapping:** Support version `18.43.45` ([eee51a8](https://github.com/ReVanced/revanced-patches/commit/eee51a863a059c5073b2817e57059e072b72155d))
* **YouTube:** Add `Enable slide to seek` patch ([68d10d4](https://github.com/ReVanced/revanced-patches/commit/68d10d4779d3545177fcf48f0aec237a2359b8b1))
* **YouTube:** Add `Remove tracking query parameter` patch ([ddda3f6](https://github.com/ReVanced/revanced-patches/commit/ddda3f6e8cd919edaa891baee6597d2566e18e50))
* **YouTube:** Bump compatibility to `18.38.45` ([9f19869](https://github.com/ReVanced/revanced-patches/commit/9f1986960cbaab84519d0685d1950764c16d08a5))
* **YouTube:** Bump compatibility to `18.44.41` ([384a0a6](https://github.com/ReVanced/revanced-patches/commit/384a0a67c52d7d342afae491388199aca6b78b4d))
* **YouTube:** Support version `18.43.45` for `Playback speed` and `Restore old video quality menu` ([c5236f8](https://github.com/ReVanced/revanced-patches/commit/c5236f812e1e362e4d03885b0950385e360bbff8))
# [2.197.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.197.0-dev.1...v2.197.0-dev.2) (2023-11-12)
### Bug Fixes
* **YouTube - Hide layout components:** Reduce false positives when hiding mix playlists ([fb173e1](https://github.com/ReVanced/revanced-patches/commit/fb173e18afd5566a4ccdbb613810fa9646da9334))
### Features
* Add `Spoof SIM country` patch ([#3116](https://github.com/ReVanced/revanced-patches/issues/3116)) ([304a0d4](https://github.com/ReVanced/revanced-patches/commit/304a0d46bfee5ae96aaefee8f508eedd16004e36))
* **YouTube - Bypass URL redirects:** Support version `18.43.45` ([e205ac7](https://github.com/ReVanced/revanced-patches/commit/e205ac761d836047c52a4862132b6ea7d5a10b1b))
* **YouTube - Hide timestamp:** Support version `18.43.45` ([9180d4f](https://github.com/ReVanced/revanced-patches/commit/9180d4f5c3d4a50f412b37af69d61aafce5ffc07))
* **YouTube - Navigation buttons:** Support version `18.43.45` ([e21286e](https://github.com/ReVanced/revanced-patches/commit/e21286e4d76323adb24ca8112a4ce03bfab98d60))
* **YouTube - Seekbar tapping:** Support version `18.43.45` ([eee51a8](https://github.com/ReVanced/revanced-patches/commit/eee51a863a059c5073b2817e57059e072b72155d))
* **YouTube:** Add `Enable slide to seek` patch ([68d10d4](https://github.com/ReVanced/revanced-patches/commit/68d10d4779d3545177fcf48f0aec237a2359b8b1))
* **YouTube:** Add `Remove tracking query parameter` patch ([ddda3f6](https://github.com/ReVanced/revanced-patches/commit/ddda3f6e8cd919edaa891baee6597d2566e18e50))
* **YouTube:** Bump compatibility to `18.38.45` ([9f19869](https://github.com/ReVanced/revanced-patches/commit/9f1986960cbaab84519d0685d1950764c16d08a5))
* **YouTube:** Bump compatibility to `18.44.41` ([384a0a6](https://github.com/ReVanced/revanced-patches/commit/384a0a67c52d7d342afae491388199aca6b78b4d))
* **YouTube:** Support version `18.43.45` for `Playback speed` and `Restore old video quality menu` ([c5236f8](https://github.com/ReVanced/revanced-patches/commit/c5236f812e1e362e4d03885b0950385e360bbff8))
# [2.197.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.197.0-dev.1...v2.197.0-dev.2) (2023-11-12)
### Bug Fixes
* **YouTube - Hide layout components:** Reduce false positives when hiding mix playlists ([aac30ad](https://github.com/ReVanced/revanced-patches/commit/aac30ad717df02af87f2d65edddac8119cb262e9))
### Features
* **YouTube - Bypass URL redirects:** Support version `18.43.45` ([8935955](https://github.com/ReVanced/revanced-patches/commit/89359550c087e457a3fa5ad924daae0735cfad55))
* **YouTube - Hide timestamp:** Support version `18.43.45` ([9180d4f](https://github.com/ReVanced/revanced-patches/commit/9180d4f5c3d4a50f412b37af69d61aafce5ffc07))
* **YouTube - Navigation buttons:** Support version `18.43.45` ([e21286e](https://github.com/ReVanced/revanced-patches/commit/e21286e4d76323adb24ca8112a4ce03bfab98d60))
* **YouTube - Seekbar tapping:** Support version `18.43.45` ([7828b14](https://github.com/ReVanced/revanced-patches/commit/7828b1425bd766db79fa8b28f002c75ff8d62cdd))
* **YouTube:** Add `Enable slide to seek` patch ([a82fa35](https://github.com/ReVanced/revanced-patches/commit/a82fa35dd8dff30fabdc5f91c48a95234ed5d055))
* **YouTube:** Add `Remove tracking query parameter` patch ([a353934](https://github.com/ReVanced/revanced-patches/commit/a3539348ce488f1effc88e62a1e0bd1a3635a2bd))
* **YouTube:** Bump compatibility to `18.38.45` ([f743491](https://github.com/ReVanced/revanced-patches/commit/f7434910ad860e92f6c8d71a1fcd063ae075b704))
* **YouTube:** Bump compatibility to `18.44.41` ([5490f58](https://github.com/ReVanced/revanced-patches/commit/5490f58974b6d5a0af145f3518756d736566adc7))
* **YouTube:** Support version `18.43.45` for `Playback speed failed` and `Restore old video quality menu` ([b5e3263](https://github.com/ReVanced/revanced-patches/commit/b5e326348a581f343a4f05ae7a8c822bc6c90313))
# [2.197.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v2.196.1-dev.6...v2.197.0-dev.1) (2023-11-12)
### Features
* **Twitch:** Support version `17.0.0` ([#3250](https://github.com/ReVanced/revanced-patches/issues/3250)) ([9c103ac](https://github.com/ReVanced/revanced-patches/commit/9c103acb94b8d7d2858441300bd297fedbacbb40))
## [2.196.1-dev.6](https://github.com/ReVanced/revanced-patches/compare/v2.196.1-dev.5...v2.196.1-dev.6) (2023-11-11)
### Bug Fixes
* **YouTube - Client spoof:** Fix low resolution precise seeking thumbnails ([#3249](https://github.com/ReVanced/revanced-patches/issues/3249)) ([0cb41ef](https://github.com/ReVanced/revanced-patches/commit/0cb41efa067d74b873167718b25893cb2e1dd240))
## [2.196.1-dev.5](https://github.com/ReVanced/revanced-patches/compare/v2.196.1-dev.4...v2.196.1-dev.5) (2023-11-10)
### Bug Fixes
* **Remove screenshot restriction:** Improve reliability ([#2938](https://github.com/ReVanced/revanced-patches/issues/2938)) ([6b7cb7b](https://github.com/ReVanced/revanced-patches/commit/6b7cb7bd38348dbe4a56385356df6ed97e81c319))
## [2.196.1-dev.4](https://github.com/ReVanced/revanced-patches/compare/v2.196.1-dev.3...v2.196.1-dev.4) (2023-11-09)
### Bug Fixes
* **YouTube - SponsorBlock:** Rename "Preview/Recap" category to "Preview/Recap/Hook" ([#3245](https://github.com/ReVanced/revanced-patches/issues/3245)) ([2cd2453](https://github.com/ReVanced/revanced-patches/commit/2cd2453658622f369b6449d5c8c33326384c2679))
## [2.196.1-dev.3](https://github.com/ReVanced/revanced-patches/compare/v2.196.1-dev.2...v2.196.1-dev.3) (2023-11-06)
### Bug Fixes
* **Nyx Music Plaer - Unlock pro:** Constrain to last working version ([96d24a3](https://github.com/ReVanced/revanced-patches/commit/96d24a3e2ef6bd323aa44a05aaf122683898e90a))
## [2.196.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.196.1-dev.1...v2.196.1-dev.2) (2023-11-06)
### Bug Fixes
* **YouTube:** Rename `Restore old seekbar thumbnails` and `Restore old quality menu` ([#3235](https://github.com/ReVanced/revanced-patches/issues/3235)) ([7e3ffc8](https://github.com/ReVanced/revanced-patches/commit/7e3ffc88631da47a032cb29a4a30fd8f5679542d))
## [2.196.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v2.196.0...v2.196.1-dev.1) (2023-11-06)
### Bug Fixes
* **YouTube - Theme:** Use consistent patch option descriptions ([#3231](https://github.com/ReVanced/revanced-patches/issues/3231)) ([c84a940](https://github.com/ReVanced/revanced-patches/commit/c84a94075ecba11e826f0b311283ef530563fe93))
# [2.196.0](https://github.com/ReVanced/revanced-patches/compare/v2.195.0...v2.196.0) (2023-11-04) # [2.196.0](https://github.com/ReVanced/revanced-patches/compare/v2.195.0...v2.196.0) (2023-11-04)

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.196.0 version = 2.197.0-dev.5

File diff suppressed because one or more lines are too long

View file

@ -8,7 +8,10 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
import com.android.tools.smali.dexlib2.iface.reference.Reference
import com.android.tools.smali.dexlib2.util.MethodUtil import com.android.tools.smali.dexlib2.util.MethodUtil
import org.w3c.dom.Node import org.w3c.dom.Node
@ -102,4 +105,23 @@ fun BytecodeContext.traverseClassHierarchy(targetClass: MutableClass, callback:
this.findClass(targetClass.superclass ?: return)?.mutableClass?.let { this.findClass(targetClass.superclass ?: return)?.mutableClass?.let {
traverseClassHierarchy(it, callback) traverseClassHierarchy(it, callback)
} }
} }
/**
* Get the [Reference] of an [Instruction] as [T].
*
* @param T The type of [Reference] to cast to.
* @return The [Reference] as [T] or null
* if the [Instruction] is not a [ReferenceInstruction] or the [Reference] is not of type [T].
* @see ReferenceInstruction
*/
inline fun <reified T : Reference> Instruction.getReference() = (this as? ReferenceInstruction)?.reference as? T
/**
* Get the index of the first [Instruction] that matches the predicate.
*
* @param predicate The predicate to match.
* @return The index of the first [Instruction] that matches the predicate.
*/
fun Method.indexOfFirstInstruction(predicate: Instruction.() -> Boolean) =
this.implementation!!.instructions.indexOfFirst(predicate)

View file

@ -4,7 +4,9 @@ import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
import app.revanced.patcher.patch.options.PatchOptionException
import org.w3c.dom.Element import org.w3c.dom.Element
import java.io.Closeable
@Patch( @Patch(
name = "Change package name", name = "Change package name",
@ -12,13 +14,11 @@ import org.w3c.dom.Element
use = false use = false
) )
@Suppress("unused") @Suppress("unused")
object ChangePackageNamePatch : ResourcePatch() { object ChangePackageNamePatch : ResourcePatch(), Closeable {
private const val DEFAULT_PACKAGE_NAME_OPTION = "Default" private val packageNameOption = stringPatchOption(
private var packageName by stringPatchOption(
key = "packageName", key = "packageName",
default = DEFAULT_PACKAGE_NAME_OPTION, default = "Default",
values = mapOf("Default" to DEFAULT_PACKAGE_NAME_OPTION), values = mapOf("Default" to "Default"),
title = "Package name", title = "Package name",
description = "The name of the package to rename the app to.", description = "The name of the package to rename the app to.",
required = true required = true
@ -26,19 +26,37 @@ object ChangePackageNamePatch : ResourcePatch() {
it == "Default" || it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$")) it == "Default" || it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$"))
} }
private lateinit var context: ResourceContext
override fun execute(context: ResourceContext) { override fun execute(context: ResourceContext) {
fun getOriginalPackageName(context: ResourceContext): String { this.context = context
context.xmlEditor["AndroidManifest.xml"].use { editor -> }
val manifest = editor.file.getElementsByTagName("manifest").item(0) as Element
return manifest.getAttribute("package")
}
}
val originalPackageName = getOriginalPackageName(context) /**
if (packageName == DEFAULT_PACKAGE_NAME_OPTION) packageName = "$originalPackageName.revanced" * Set the package name to use.
* If this is called multiple times, the first call will set the package name.
*
* @param fallbackPackageName The package name to use if the user has not already specified a package name.
* @return The package name that was set.
* @throws PatchOptionException.ValueValidationException If the package name is invalid.
*/
fun setOrGetFallbackPackageName(fallbackPackageName: String): String {
val packageName = this.packageNameOption.value!!
context["AndroidManifest.xml"].apply { return if (packageName == this.packageNameOption.default)
readText().replace(originalPackageName, packageName!!).let(::writeText) fallbackPackageName.also { this.packageNameOption.value = it }
} else
packageName
}
override fun close() = context.xmlEditor["AndroidManifest.xml"].use { editor ->
val manifest = editor.file.getElementsByTagName("manifest").item(0) as Element
val originalPackageName = manifest.getAttribute("package")
var replacementPackageName = this.packageNameOption.value
if (replacementPackageName == this.packageNameOption.default)
replacementPackageName = "$originalPackageName.revanced"
manifest.setAttribute("package", replacementPackageName)
} }
} }

View file

@ -1,14 +1,19 @@
package app.revanced.patches.all.screenshot.removerestriction package app.revanced.patches.all.screenshot.removerestriction
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.util.patch.AbstractTransformInstructionsPatch import app.revanced.util.patch.AbstractTransformInstructionsPatch
import app.revanced.util.patch.IMethodCall import app.revanced.util.patch.IMethodCall
import app.revanced.util.patch.Instruction35cInfo import app.revanced.util.patch.Instruction35cInfo
import app.revanced.util.patch.filterMapInstruction35c import app.revanced.util.patch.filterMapInstruction35c
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.ClassDef import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.Instruction import com.android.tools.smali.dexlib2.iface.instruction.Instruction
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22c
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
@Patch( @Patch(
name = "Remove screenshot restriction", name = "Remove screenshot restriction",
@ -22,6 +27,11 @@ object RemoveScreenshotRestrictionPatch : AbstractTransformInstructionsPatch<Ins
"Lapp/revanced/all/screenshot/removerestriction/RemoveScreenshotRestrictionPatch" "Lapp/revanced/all/screenshot/removerestriction/RemoveScreenshotRestrictionPatch"
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "$INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX;" private const val INTEGRATIONS_CLASS_DESCRIPTOR = "$INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX;"
override fun execute(context: BytecodeContext) {
super.execute(context)
ModifyLayoutParamsFlags().execute(context)
}
override fun filterMap( override fun filterMap(
classDef: ClassDef, classDef: ClassDef,
method: Method, method: Method,
@ -46,6 +56,12 @@ object RemoveScreenshotRestrictionPatch : AbstractTransformInstructionsPatch<Ins
override val methodParams: Array<String>, override val methodParams: Array<String>,
override val returnType: String override val returnType: String
): IMethodCall { ): IMethodCall {
AddFlags(
"Landroid/view/Window;",
"addFlags",
arrayOf("I"),
"V",
),
SetFlags( SetFlags(
"Landroid/view/Window;", "Landroid/view/Window;",
"setFlags", "setFlags",
@ -54,3 +70,37 @@ object RemoveScreenshotRestrictionPatch : AbstractTransformInstructionsPatch<Ins
); );
} }
} }
private class ModifyLayoutParamsFlags : AbstractTransformInstructionsPatch<Pair<Instruction22c, Int>>() {
override fun filterMap(
classDef: ClassDef,
method: Method,
instruction: Instruction,
instructionIndex: Int
): Pair<Instruction22c, Int>? {
if (instruction.opcode != Opcode.IPUT) {
return null
}
val instruction22c = instruction as Instruction22c
val fieldReference = instruction22c.reference as FieldReference
if (fieldReference.definingClass != "Landroid/view/WindowManager\$LayoutParams;"
|| fieldReference.name != "flags"
|| fieldReference.type != "I") {
return null
}
return Pair(instruction22c, instructionIndex)
}
override fun transform(mutableMethod: MutableMethod, entry: Pair<Instruction22c, Int>) {
val (instruction, index) = entry
val register = instruction.registerA
mutableMethod.addInstructions(
index,
"and-int/lit16 v$register, v$register, -0x2001"
)
}
}

View file

@ -0,0 +1,111 @@
package app.revanced.patches.all.telephony.sim.spoof
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.patch.options.PatchOption
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.util.patch.AbstractTransformInstructionsPatch
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference
import com.android.tools.smali.dexlib2.util.MethodUtil
import java.util.*
@Patch(
name = "Spoof SIM country",
description = "Spoofs country information returned by the SIM card provider.",
use = false,
)
@Suppress("unused")
object SpoofSimCountryPatch : AbstractTransformInstructionsPatch<Pair<Int, String>>() {
private val isoValidator: PatchOption<String>.(String?) -> Boolean =
{ it: String? -> it?.uppercase() in Locale.getISOCountries() || it == null }
private val networkCountryIso by stringPatchOption(
"networkCountryIso",
null,
null,
"Network ISO Country Code",
"ISO-3166-1 alpha-2 country code equivalent of the MCC (Mobile Country Code) " +
"of the current registered operator or the cell nearby.",
validator = isoValidator
)
private val simCountryIso by stringPatchOption(
"simCountryIso",
null,
null,
"Sim ISO Country Code",
"ISO-3166-1 alpha-2 country code equivalent for the SIM provider's country code.",
validator = isoValidator
)
override fun filterMap(
classDef: ClassDef,
method: Method,
instruction: Instruction,
instructionIndex: Int
): Pair<Int, String>? {
if (instruction !is ReferenceInstruction) return null
val reference = instruction.reference as? MethodReference ?: return null
val match = MethodCall.entries.firstOrNull { search ->
MethodUtil.methodSignaturesMatch(reference, search.reference)
} ?: return null
val iso = when (match) {
MethodCall.NetworkCountryIso -> networkCountryIso
MethodCall.SimCountryIso -> simCountryIso
}?.lowercase()
return iso?.let { instructionIndex to it }
}
override fun transform(
mutableMethod: MutableMethod,
entry: Pair<Int, String>
) = transformMethodCall(entry, mutableMethod)
private fun transformMethodCall(
entry: Pair<Int, String>,
mutableMethod: MutableMethod
) {
val (instructionIndex, methodCallValue) = entry
val register = mutableMethod.getInstruction<OneRegisterInstruction>(instructionIndex + 1).registerA
mutableMethod.replaceInstruction(
instructionIndex + 1,
"const-string v$register, \"$methodCallValue\""
)
}
private enum class MethodCall(
val reference: MethodReference
) {
NetworkCountryIso(
ImmutableMethodReference(
"Landroid/telephony/TelephonyManager;",
"getNetworkCountryIso",
emptyList(),
"Ljava/lang/String;"
)
),
SimCountryIso(
ImmutableMethodReference(
"Landroid/telephony/TelephonyManager;",
"getSimCountryIso",
emptyList(),
"Ljava/lang/String;"
)
)
}
}

View file

@ -0,0 +1,26 @@
package app.revanced.patches.facebook.ads.story
import app.revanced.extensions.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.facebook.ads.story.fingerprints.AdsInsertionFingerprint
import app.revanced.patches.facebook.ads.story.fingerprints.FetchMoreAdsFingerprint
@Patch(
name = "Hide story ads",
description = "Hides the ads in the Facebook app stories.",
compatiblePackages = [CompatiblePackage("com.facebook.katana")]
)
@Suppress("unused")
object HideStoryAdsPatch : BytecodePatch(
setOf(FetchMoreAdsFingerprint, AdsInsertionFingerprint)
) {
override fun execute(context: BytecodeContext) =
setOf(FetchMoreAdsFingerprint, AdsInsertionFingerprint).forEach { fingerprint ->
fingerprint.result?.mutableMethod?.replaceInstruction(0, "return-void")
?: throw fingerprint.exception
}
}

View file

@ -0,0 +1,3 @@
package app.revanced.patches.facebook.ads.story.fingerprints
object AdsInsertionFingerprint : FieldMethodFingerprint(fieldValue = "AdBucketDataSourceUtil\$attemptAdsInsertion\$1")

View file

@ -0,0 +1,3 @@
package app.revanced.patches.facebook.ads.story.fingerprints
object FetchMoreAdsFingerprint : FieldMethodFingerprint(fieldValue = "AdBucketDataSourceUtil\$attemptFetchMoreAds\$1")

View file

@ -0,0 +1,15 @@
package app.revanced.patches.facebook.ads.story.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.iface.value.StringEncodedValue
abstract class FieldMethodFingerprint(fieldValue: String) : MethodFingerprint(
returnType = "V",
parameters = listOf(),
customFingerprint = { methodDef, classDef ->
methodDef.name == "run" && classDef.fields.any any@{ field ->
if (field.name != "__redex_internal_original_name") return@any false
(field.initialValue as? StringEncodedValue)?.value == fieldValue
}
}
)

View file

@ -4,18 +4,25 @@ import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.all.misc.packagename.ChangePackageNamePatch
import app.revanced.patches.music.misc.microg.fingerprints.* import app.revanced.patches.music.misc.microg.fingerprints.*
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_PACKAGE_NAME import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_PACKAGE_NAME
import app.revanced.patches.youtube.misc.microg.shared.Constants
import app.revanced.util.microg.MicroGBytecodeHelper import app.revanced.util.microg.MicroGBytecodeHelper
@Patch( @Patch(
name = "Vanced MicroG support", name = "Vanced MicroG support",
description = "Allows YouTube Music to run without root and under a different package name.", description = "Allows YouTube Music to run without root and under a different package name.",
dependencies = [MicroGResourcePatch::class], dependencies = [
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")] ChangePackageNamePatch::class,
MicroGResourcePatch::class,
],
compatiblePackages = [
CompatiblePackage(
"com.google.android.apps.youtube.music"
)
]
) )
@Suppress("unused") @Suppress("unused")
object MicroGBytecodePatch : BytecodePatch( object MicroGBytecodePatch : BytecodePatch(
@ -35,25 +42,29 @@ object MicroGBytecodePatch : BytecodePatch(
// - "com.google.android.gms.phenotype.PACKAGE_NAME", // - "com.google.android.gms.phenotype.PACKAGE_NAME",
// - "com.google.android.gms.phenotype.UPDATE", // - "com.google.android.gms.phenotype.UPDATE",
// - "com.google.android.gms.phenotype", // - "com.google.android.gms.phenotype",
override fun execute(context: BytecodeContext) = MicroGBytecodeHelper.patchBytecode( override fun execute(context: BytecodeContext) {
context, val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(REVANCED_MUSIC_PACKAGE_NAME)
arrayOf(
MicroGBytecodeHelper.packageNameTransform( MicroGBytecodeHelper.patchBytecode(
Constants.PACKAGE_NAME, context,
Constants.REVANCED_PACKAGE_NAME arrayOf(
MicroGBytecodeHelper.packageNameTransform(
MUSIC_PACKAGE_NAME,
packageName
)
),
MicroGBytecodeHelper.PrimeMethodTransformationData(
PrimeFingerprint,
MUSIC_PACKAGE_NAME,
packageName
),
listOf(
ServiceCheckFingerprint,
GooglePlayUtilityFingerprint,
CastDynamiteModuleFingerprint,
CastDynamiteModuleV2Fingerprint,
CastContextFetchFingerprint
) )
),
MicroGBytecodeHelper.PrimeMethodTransformationData(
PrimeFingerprint,
MUSIC_PACKAGE_NAME,
REVANCED_MUSIC_PACKAGE_NAME
),
listOf(
ServiceCheckFingerprint,
GooglePlayUtilityFingerprint,
CastDynamiteModuleFingerprint,
CastDynamiteModuleV2Fingerprint,
CastContextFetchFingerprint
) )
) }
} }

View file

@ -3,6 +3,7 @@ package app.revanced.patches.music.misc.microg
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.all.misc.packagename.ChangePackageNamePatch
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
@ -14,15 +15,18 @@ import app.revanced.util.microg.MicroGResourceHelper
@Patch( @Patch(
description = "Resource patch to allow YouTube Music ReVanced to run without root " + description = "Resource patch to allow YouTube Music ReVanced to run without root " +
"and under a different package name." "and under a different package name.",
dependencies = [ChangePackageNamePatch::class]
) )
object MicroGResourcePatch : ResourcePatch() { object MicroGResourcePatch : ResourcePatch() {
override fun execute(context: ResourceContext) { override fun execute(context: ResourceContext) {
val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(REVANCED_MUSIC_PACKAGE_NAME)
// update manifest // update manifest
MicroGResourceHelper.patchManifest( MicroGResourceHelper.patchManifest(
context, context,
MUSIC_PACKAGE_NAME, MUSIC_PACKAGE_NAME,
REVANCED_MUSIC_PACKAGE_NAME, packageName,
REVANCED_MUSIC_APP_NAME REVANCED_MUSIC_APP_NAME
) )

View file

@ -10,7 +10,7 @@ import app.revanced.patches.nyx.misc.pro.fingerprints.CheckProFingerprint
@Patch( @Patch(
name = "Unlock pro", name = "Unlock pro",
compatiblePackages = [CompatiblePackage("com.awedea.nyx")] compatiblePackages = [CompatiblePackage("com.awedea.nyx", ["2.2.7"])]
) )
@Suppress("unused") @Suppress("unused")
object UnlockProPatch : BytecodePatch(setOf(CheckProFingerprint)) { object UnlockProPatch : BytecodePatch(setOf(CheckProFingerprint)) {

View file

@ -32,21 +32,29 @@ abstract class AbstractPreferenceScreen(
preferences: MutableList<BasePreference> = mutableListOf(), preferences: MutableList<BasePreference> = mutableListOf(),
val categories: MutableList<Category> = mutableListOf() val categories: MutableList<Category> = mutableListOf()
) : BasePreferenceCollection(key, title, preferences) { ) : BasePreferenceCollection(key, title, preferences) {
override fun transform(): PreferenceScreen { override fun transform() = PreferenceScreen(
return PreferenceScreen( key,
key, StringResource(
StringResource("${key}_title", title), "${key}_title", title
preferences.sortedBy { it.title.value.removePunctuation().lowercase() } + ),
categories.sortedBy { it.title.removePunctuation().lowercase() }.map { it.transform() }, preferences.sortedWith(
summary?.let { summary -> compareBy(
StringResource("${key}_summary", summary) { it is PreferenceScreen },
} { it.title.value.removePunctuation().lowercase() }
) )
} ) + categories.sortedBy {
it.title.removePunctuation().lowercase()
}.map {
it.transform()
},
summary?.let { summary ->
StringResource("${key}_summary", summary)
}
)
private fun ensureScreenInserted() { private fun ensureScreenInserted() {
// Add to screens if not yet done // Add to screens if not yet done
if(!this@AbstractPreferenceScreen.root.contains(this)) if (!this@AbstractPreferenceScreen.root.contains(this))
this@AbstractPreferenceScreen.root.add(this) this@AbstractPreferenceScreen.root.add(this)
} }
@ -59,7 +67,7 @@ abstract class AbstractPreferenceScreen(
key: String, key: String,
title: String, title: String,
preferences: MutableList<BasePreference> = mutableListOf() preferences: MutableList<BasePreference> = mutableListOf()
): BasePreferenceCollection(key, title, preferences) { ) : BasePreferenceCollection(key, title, preferences) {
override fun transform(): PreferenceCategory { override fun transform(): PreferenceCategory {
return PreferenceCategory( return PreferenceCategory(
key, key,
@ -72,7 +80,7 @@ abstract class AbstractPreferenceScreen(
ensureScreenInserted() ensureScreenInserted()
// Add to categories if not yet done // Add to categories if not yet done
if(!this@Screen.categories.contains(this)) if (!this@Screen.categories.contains(this))
this@Screen.categories.add(this) this@Screen.categories.add(this)
this.preferences.addAll(preferences) this.preferences.addAll(preferences)

View file

@ -1,52 +0,0 @@
package app.revanced.patches.twelvewidgets.unlock
import app.revanced.extensions.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.twelvewidgets.unlock.fingerprints.*
@Patch(
name = "Unlock paid widgets",
description = "Unlocks paid widgets of the app",
compatiblePackages = [CompatiblePackage("com.dci.dev.androidtwelvewidgets")]
)
@Suppress("unused")
object UnlockPaidWidgetsPatch : BytecodePatch(
setOf(
AgendaDaysWidgetUnlockFingerprint,
CalendarBigWidgetUnlockFingerprint,
CalendarWideDayEventsWidgetUnlockFingerprint,
CalendarWideTimelineWidgetUnlockFingerprint,
ScreentimeSmallWidgetUnlockFingerprint,
WeatherWidgetUnlockFingerprint
)
) {
override fun execute(context: BytecodeContext) {
listOf(
AgendaDaysWidgetUnlockFingerprint,
CalendarBigWidgetUnlockFingerprint,
CalendarWideDayEventsWidgetUnlockFingerprint,
CalendarWideTimelineWidgetUnlockFingerprint,
ScreentimeSmallWidgetUnlockFingerprint,
WeatherWidgetUnlockFingerprint
).map { fingerprint ->
fingerprint.result?.mutableMethod ?: throw fingerprint.exception
}.forEach { method ->
method.apply {
removeInstructions(4, 3)
addInstructions(
implementation?.instructions?.size!!,
"""
const/4 v1, 0x0
invoke-virtual {v0, v1}, Landroid/view/View;->setVisibility(I)V
return-object v0
"""
)
}
}
}
}

View file

@ -1,3 +0,0 @@
package app.revanced.patches.twelvewidgets.unlock.fingerprints
object AgendaDaysWidgetUnlockFingerprint : MethodUnlockFingerprint("AgendaDaysWidgetConfigureActivity")

View file

@ -1,3 +0,0 @@
package app.revanced.patches.twelvewidgets.unlock.fingerprints
object CalendarBigWidgetUnlockFingerprint : MethodUnlockFingerprint("CalendarBigWidgetConfigureActivity")

View file

@ -1,4 +0,0 @@
package app.revanced.patches.twelvewidgets.unlock.fingerprints
object CalendarWideDayEventsWidgetUnlockFingerprint :
MethodUnlockFingerprint("CalendarWideDayEventsWidgetConfigureActivity")

View file

@ -1,4 +0,0 @@
package app.revanced.patches.twelvewidgets.unlock.fingerprints
object CalendarWideTimelineWidgetUnlockFingerprint :
MethodUnlockFingerprint("CalendarWideTimelineWidgetConfigureActivity")

View file

@ -1,12 +0,0 @@
package app.revanced.patches.twelvewidgets.unlock.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
abstract class MethodUnlockFingerprint(private val className: String) : MethodFingerprint(
"L",
strings = listOf("binding.addButton"),
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/$className;")
}
)

View file

@ -1,3 +0,0 @@
package app.revanced.patches.twelvewidgets.unlock.fingerprints
object ScreentimeSmallWidgetUnlockFingerprint : MethodUnlockFingerprint("ScreentimeSmallWidgetConfigureActivity")

View file

@ -1,3 +0,0 @@
package app.revanced.patches.twelvewidgets.unlock.fingerprints
object WeatherWidgetUnlockFingerprint : MethodUnlockFingerprint("WeatherWidgetConfigureActivity")

View file

@ -17,7 +17,7 @@ import app.revanced.patches.twitch.misc.settings.SettingsPatch
name = "Block audio ads", name = "Block audio ads",
description = "Blocks audio ads in streams and VODs.", description = "Blocks audio ads in streams and VODs.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class], dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [CompatiblePackage("tv.twitch.android.app", ["15.4.1", "16.1.0"])], compatiblePackages = [CompatiblePackage("tv.twitch.android.app", ["15.4.1", "16.1.0", "17.0.0", "17.1.0"])],
) )
@Suppress("unused") @Suppress("unused")
object AudioAdsPatch : BytecodePatch( object AudioAdsPatch : BytecodePatch(

View file

@ -18,7 +18,7 @@ import app.revanced.patches.twitch.misc.settings.SettingsPatch
name = "Block embedded ads", name = "Block embedded ads",
description = "Blocks embedded stream ads using services like Luminous or PurpleAdBlocker.", description = "Blocks embedded stream ads using services like Luminous or PurpleAdBlocker.",
dependencies = [VideoAdsPatch::class, IntegrationsPatch::class, SettingsPatch::class], dependencies = [VideoAdsPatch::class, IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [CompatiblePackage("tv.twitch.android.app", ["15.4.1", "16.1.0"])] compatiblePackages = [CompatiblePackage("tv.twitch.android.app", ["15.4.1", "16.1.0", "17.0.0", "17.1.0"])]
) )
@Suppress("unused") @Suppress("unused")
object EmbeddedAdsPatch : BytecodePatch( object EmbeddedAdsPatch : BytecodePatch(

View file

@ -21,7 +21,7 @@ import app.revanced.patches.twitch.misc.settings.SettingsPatch
name = "Block video ads", name = "Block video ads",
description = "Blocks video ads in streams and VODs.", description = "Blocks video ads in streams and VODs.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class], dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [CompatiblePackage("tv.twitch.android.app", ["15.4.1", "16.1.0"])] compatiblePackages = [CompatiblePackage("tv.twitch.android.app", ["15.4.1", "16.1.0", "17.0.0", "17.1.0"])]
) )
object VideoAdsPatch : AbstractAdPatch( object VideoAdsPatch : AbstractAdPatch(
"Lapp/revanced/twitch/patches/VideoAdsPatch;->shouldBlockVideoAds()Z", "Lapp/revanced/twitch/patches/VideoAdsPatch;->shouldBlockVideoAds()Z",

View file

@ -22,7 +22,7 @@ import app.revanced.patches.twitch.misc.settings.SettingsPatch
name = "Show deleted messages", name = "Show deleted messages",
description = "Shows deleted chat messages behind a clickable spoiler.", description = "Shows deleted chat messages behind a clickable spoiler.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class], dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [CompatiblePackage("tv.twitch.android.app", ["15.4.1", "16.1.0"])] compatiblePackages = [CompatiblePackage("tv.twitch.android.app", ["15.4.1", "16.1.0", "17.0.0", "17.1.0"])]
) )
@Suppress("unused") @Suppress("unused")
object ShowDeletedMessagesPatch : BytecodePatch( object ShowDeletedMessagesPatch : BytecodePatch(

View file

@ -17,7 +17,7 @@ import app.revanced.patches.twitch.misc.settings.SettingsPatch
name = "Auto claim channel points", name = "Auto claim channel points",
description = "Automatically claim Channel Points.", description = "Automatically claim Channel Points.",
dependencies = [SettingsPatch::class], dependencies = [SettingsPatch::class],
compatiblePackages = [CompatiblePackage("tv.twitch.android.app", ["15.4.1", "16.1.0"])] compatiblePackages = [CompatiblePackage("tv.twitch.android.app", ["15.4.1", "16.1.0", "17.0.0", "17.1.0"])]
) )
@Suppress("unused") @Suppress("unused")
object AutoClaimChannelPointPatch : BytecodePatch( object AutoClaimChannelPointPatch : BytecodePatch(

View file

@ -33,7 +33,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -27,7 +27,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -31,7 +31,10 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -26,7 +26,10 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -26,7 +26,10 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
), ),
] ]

View file

@ -24,7 +24,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
[ [
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -27,14 +27,9 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
CompatiblePackage( CompatiblePackage(
"com.google.android.youtube", "com.google.android.youtube",
[ [
"18.16.37", "18.43.45",
"18.19.35", "18.44.41",
"18.20.39", "18.45.41"
"18.23.35",
"18.29.38",
"18.32.39",
"18.37.36",
"18.38.44"
] ]
) )
] ]
@ -64,8 +59,8 @@ object EnableSeekbarTappingPatch : BytecodePatch(
.reference as MethodReference .reference as MethodReference
buildMap { buildMap {
put("O", getReference(patternScanResult.endIndex))
put("N", getReference(patternScanResult.startIndex)) put("N", getReference(patternScanResult.startIndex))
put("O", getReference(patternScanResult.endIndex))
} }
} }

View file

@ -0,0 +1,84 @@
package app.revanced.patches.youtube.interaction.seekbar
import app.revanced.extensions.exception
import app.revanced.patcher.data.BytecodeContext
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.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.DoubleSpeedSeekNoticeFingerprint
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.SlideToSeekFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Enable slide to seek",
description = "Enable slide to seek instead of playing at 2x speed.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"18.43.45",
"18.44.41",
"18.45.41"
]
)
]
)
@Suppress("unused")
object EnableSlideToSeekPatch : BytecodePatch(
setOf(
SlideToSeekFingerprint,
DoubleSpeedSeekNoticeFingerprint
)
) {
const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/SlideToSeekPatch;"
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
SwitchPreference(
"revanced_slide_to_seek",
StringResource(
"revanced_slide_to_seek_title",
"Enable slide to seek"
),
StringResource(
"revanced_slide_to_seek_summary_on",
"Slide to seek is enabled"
),
StringResource(
"revanced_slide_to_seek_summary_off",
"Slide to seek is not enabled"
),
)
)
arrayOf(
// Restore the behaviour to slide to seek.
SlideToSeekFingerprint,
// Disable the double speed seek notice.
DoubleSpeedSeekNoticeFingerprint
).map {
it.result ?: throw it.exception
}.forEach {
val insertIndex = it.scanResult.patternScanResult!!.endIndex + 1
it.mutableMethod.apply {
val isEnabledRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstructions(
insertIndex,
"""
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->isSlideToSeekDisabled()Z
move-result v$isEnabledRegister
"""
)
}
}
}
}

View file

@ -0,0 +1,11 @@
package app.revanced.patches.youtube.interaction.seekbar.fingerprints
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.Opcode
object DoubleSpeedSeekNoticeFingerprint : LiteralValueFingerprint(
returnType = "Z",
parameters = emptyList(),
opcodes = listOf(Opcode.MOVE_RESULT),
literalSupplier = { 45411330 }
)

View file

@ -4,6 +4,10 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
object IsSwipingUpFingerprint : MethodFingerprint( object IsSwipingUpFingerprint : MethodFingerprint(
returnType = "Z",
parameters = listOf("Landroid/view/MotionEvent;", "J"), parameters = listOf("Landroid/view/MotionEvent;", "J"),
opcodes = listOf(Opcode.SGET_OBJECT) opcodes = listOf(
Opcode.SGET_OBJECT,
Opcode.IGET_OBJECT
)
) )

View file

@ -1,8 +1,8 @@
package app.revanced.patches.youtube.interaction.seekbar.fingerprints package app.revanced.patches.youtube.interaction.seekbar.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
@ -12,7 +12,7 @@ object OnTouchEventHandlerFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.PUBLIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.PUBLIC,
parameters = listOf("L"), parameters = listOf("L"),
opcodes = listOf( opcodes = listOf(
Opcode.INVOKE_VIRTUAL, // oMethodReference Opcode.INVOKE_VIRTUAL, // nMethodReference
Opcode.RETURN, Opcode.RETURN,
Opcode.IGET_OBJECT, Opcode.IGET_OBJECT,
Opcode.IGET_BOOLEAN, Opcode.IGET_BOOLEAN,
@ -23,10 +23,9 @@ object OnTouchEventHandlerFingerprint : MethodFingerprint(
Opcode.INT_TO_FLOAT, Opcode.INT_TO_FLOAT,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT, Opcode.MOVE_RESULT,
Opcode.IF_NEZ, Opcode.IF_EQZ,
Opcode.RETURN,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.INVOKE_VIRTUAL, // pMethodReference Opcode.INVOKE_VIRTUAL, // oMethodReference
), ),
customFingerprint = { methodDef, _ -> methodDef.name == "onTouchEvent" } customFingerprint = { methodDef, _ -> methodDef.name == "onTouchEvent" }
) )

View file

@ -0,0 +1,11 @@
package app.revanced.patches.youtube.interaction.seekbar.fingerprints
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.Opcode
object SlideToSeekFingerprint : LiteralValueFingerprint(
returnType = "Z",
parameters = emptyList(),
opcodes = listOf(Opcode.MOVE_RESULT),
literalSupplier = { 45411329 }
)

View file

@ -33,7 +33,10 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -31,7 +31,10 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
], ],

View file

@ -29,7 +29,10 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -39,7 +39,10 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -30,7 +30,10 @@ import com.android.tools.smali.dexlib2.Opcode
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -15,7 +15,6 @@ import app.revanced.patches.youtube.layout.buttons.navigation.utils.InjectionUti
import app.revanced.patches.youtube.layout.buttons.navigation.utils.InjectionUtils.injectHook import app.revanced.patches.youtube.layout.buttons.navigation.utils.InjectionUtils.injectHook
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch import app.revanced.patches.youtube.misc.settings.SettingsPatch
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch( @Patch(
@ -37,7 +36,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]
@ -98,6 +100,10 @@ object NavigationButtonsPatch : BytecodePatch(
), ),
), ),
), ),
StringResource(
"revanced_navigation_buttons_preference_screen_summary",
"Hide or change buttons in the navigation bar"
)
) )
) )
@ -177,13 +183,7 @@ object NavigationButtonsPatch : BytecodePatch(
} }
PivotBarCreateButtonViewFingerprint.result!!.apply { PivotBarCreateButtonViewFingerprint.result!!.apply {
val insertIndex = mutableMethod.implementation!!.instructions.let { val insertIndex = scanResult.patternScanResult!!.endIndex
val scanStart = scanResult.patternScanResult!!.endIndex
scanStart + it.subList(scanStart, it.size - 1).indexOfFirst { instruction ->
instruction.opcode == Opcode.INVOKE_STATIC
}
}
/* /*
* Inject hooks * Inject hooks

View file

@ -5,7 +5,9 @@ import com.android.tools.smali.dexlib2.Opcode
object PivotBarCreateButtonViewFingerprint : MethodFingerprint( object PivotBarCreateButtonViewFingerprint : MethodFingerprint(
opcodes = listOf( opcodes = listOf(
Opcode.MOVE_OBJECT, Opcode.INVOKE_DIRECT_RANGE,
Opcode.INVOKE_DIRECT_RANGE, // unique instruction anchor Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC
) )
) )

View file

@ -34,7 +34,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction3rc
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -29,7 +29,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -29,7 +29,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -28,7 +28,10 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -29,7 +29,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -32,7 +32,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -29,7 +29,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -25,7 +25,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -20,7 +20,10 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
CompatiblePackage( CompatiblePackage(
"com.google.android.youtube", [ "com.google.android.youtube", [
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -11,10 +11,7 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.settings.preference.impl.InputType import app.revanced.patches.shared.settings.preference.impl.*
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.youtube.layout.hide.general.fingerprints.ParseElementFromBufferFingerprint import app.revanced.patches.youtube.layout.hide.general.fingerprints.ParseElementFromBufferFingerprint
import app.revanced.patches.youtube.layout.hide.general.fingerprints.PlayerOverlayFingerprint import app.revanced.patches.youtube.layout.hide.general.fingerprints.PlayerOverlayFingerprint
import app.revanced.patches.youtube.layout.hide.general.fingerprints.ShowWatermarkFingerprint import app.revanced.patches.youtube.layout.hide.general.fingerprints.ShowWatermarkFingerprint
@ -23,6 +20,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch.PreferenceScreen import app.revanced.patches.youtube.misc.settings.SettingsPatch.PreferenceScreen
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@Patch( @Patch(
name = "Hide layout components", name = "Hide layout components",
@ -36,7 +34,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
"com.google.android.youtube", [ "com.google.android.youtube", [
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]
@ -45,8 +46,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
object HideLayoutComponentsPatch : BytecodePatch( object HideLayoutComponentsPatch : BytecodePatch(
setOf(ParseElementFromBufferFingerprint, PlayerOverlayFingerprint) setOf(ParseElementFromBufferFingerprint, PlayerOverlayFingerprint)
) { ) {
private const val FILTER_CLASS_DESCRIPTOR = private const val LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/components/LayoutComponentsFilter;" "Lapp/revanced/integrations/patches/components/LayoutComponentsFilter;"
private const val DESCRIPTION_COMPONENTS_FILTER_CLASS_NAME =
"Lapp/revanced/integrations/patches/components/DescriptionComponentsFilter;"
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
PreferenceScreen.LAYOUT.addPreferences( PreferenceScreen.LAYOUT.addPreferences(
@ -284,7 +287,95 @@ object HideLayoutComponentsPatch : BytecodePatch(
StringResource("revanced_hide_chips_shelf_on", "Chips shelf is hidden"), StringResource("revanced_hide_chips_shelf_on", "Chips shelf is hidden"),
StringResource("revanced_hide_chips_shelf_off", "Chips shelf is shown") StringResource("revanced_hide_chips_shelf_off", "Chips shelf is shown")
), ),
app.revanced.patches.shared.settings.preference.impl.PreferenceScreen( PreferenceScreen(
"revanced_hide_description_components_preference_screen",
StringResource(
"revanced_hide_description_components_preference_screen_title",
"Hide components in the video description"
),
listOf(
SwitchPreference(
"revanced_hide_info_cards_section",
StringResource(
"revanced_hide_info_cards_section_title",
"Hide info cards section"
),
StringResource(
"revanced_hide_info_cards_section_summary_on",
"Info cards section is hidden"
),
StringResource(
"revanced_hide_info_cards_section_summary_off",
"Info cards section is shown"
)
),
SwitchPreference(
"revanced_hide_game_section",
StringResource(
"revanced_hide_game_section_title",
"Hide game section"
),
StringResource(
"revanced_hide_game_section_summary_on",
"Game section is hidden"
),
StringResource(
"revanced_hide_game_section_summary_off",
"Game section is shown"
)
),
SwitchPreference(
"revanced_hide_music_section",
StringResource(
"revanced_hide_music_section_title",
"Hide music section"
),
StringResource(
"revanced_hide_music_section_summary_on",
"Music section is hidden"
),
StringResource(
"revanced_hide_music_section_summary_off",
"Music section is shown"
)
),
SwitchPreference(
"revanced_hide_podcast_section",
StringResource(
"revanced_hide_podcast_section_title",
"Hide podcast section"
),
StringResource(
"revanced_hide_podcast_section_summary_on",
"Podcast section is hidden"
),
StringResource(
"revanced_hide_podcast_section_summary_off",
"Podcast section is shown"
)
),
SwitchPreference(
"revanced_hide_transcript_section",
StringResource(
"revanced_hide_transcript_section_title",
"Hide transcript section"
),
StringResource(
"revanced_hide_transcript_section_summary_on",
"Transcript section is hidden"
),
StringResource(
"revanced_hide_transcript_section_summary_off",
"Transcript section is shown"
)
),
),
StringResource(
"revanced_hide_description_components_preference_screen_summary",
"Hide components under the video description"
)
),
PreferenceScreen(
"revanced_custom_filter_preference_screen", "revanced_custom_filter_preference_screen",
StringResource("revanced_custom_filter_preference_screen_title", "Custom filter"), StringResource("revanced_custom_filter_preference_screen_title", "Custom filter"),
listOf( listOf(
@ -313,11 +404,16 @@ object HideLayoutComponentsPatch : BytecodePatch(
), ),
inputType = InputType.TEXT_MULTI_LINE inputType = InputType.TEXT_MULTI_LINE
) )
),
StringResource(
"revanced_custom_filter_preference_screen_summary",
"Hide components using custom filters"
) )
) )
) )
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR) LithoFilterPatch.addFilter(LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR)
LithoFilterPatch.addFilter(DESCRIPTION_COMPONENTS_FILTER_CLASS_NAME)
// region Mix playlists // region Mix playlists
@ -327,12 +423,15 @@ object HideLayoutComponentsPatch : BytecodePatch(
result.mutableMethod.apply { result.mutableMethod.apply {
val consumeByteBufferIndex = result.scanResult.patternScanResult!!.startIndex val consumeByteBufferIndex = result.scanResult.patternScanResult!!.startIndex
val byteBufferRegister = getInstruction<FiveRegisterInstruction>(consumeByteBufferIndex).registerD val conversionContextRegister =
getInstruction<TwoRegisterInstruction>(consumeByteBufferIndex - 2).registerA
val byteBufferRegister =
getInstruction<FiveRegisterInstruction>(consumeByteBufferIndex).registerD
addInstructionsWithLabels( addInstructionsWithLabels(
result.scanResult.patternScanResult!!.startIndex, consumeByteBufferIndex,
""" """
invoke-static {v$byteBufferRegister}, $FILTER_CLASS_DESCRIPTOR->filterMixPlaylists([B)Z invoke-static {v$conversionContextRegister, v$byteBufferRegister}, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->filterMixPlaylists(Ljava/lang/Object;[B)Z
move-result v0 # Conveniently same register happens to be free. move-result v0 # Conveniently same register happens to be free.
if-nez v0, :return_empty_component if-nez v0, :return_empty_component
""", """,
@ -355,7 +454,7 @@ object HideLayoutComponentsPatch : BytecodePatch(
addInstructions( addInstructions(
index, index,
""" """
invoke-static {}, $FILTER_CLASS_DESCRIPTOR->showWatermark()Z invoke-static {}, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->showWatermark()Z
move-result p2 move-result p2
""" """
) )

View file

@ -36,7 +36,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -25,7 +25,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -25,7 +25,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -28,7 +28,10 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41",
]) ])
] ]
) )

View file

@ -33,7 +33,10 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -37,7 +37,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -19,7 +19,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
CompatiblePackage( CompatiblePackage(
"com.google.android.youtube", [ "com.google.android.youtube", [
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -26,7 +26,10 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -1,24 +1,25 @@
package app.revanced.patches.youtube.layout.hide.time.fingerprints package app.revanced.patches.youtube.layout.hide.time.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
@FuzzyPatternScanMethod(1) @FuzzyPatternScanMethod(1)
object TimeCounterFingerprint : MethodFingerprint( object TimeCounterFingerprint : MethodFingerprint(
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf( "V",
Opcode.IGET_OBJECT, AccessFlags.PUBLIC or AccessFlags.FINAL,
emptyList(),
listOf(
Opcode.SUB_LONG_2ADDR,
Opcode.IGET_WIDE, Opcode.IGET_WIDE,
Opcode.CONST_WIDE_16, Opcode.SUB_LONG_2ADDR,
Opcode.CMP_LONG,
Opcode.IF_LEZ,
Opcode.IGET_OBJECT, Opcode.IGET_OBJECT,
Opcode.IF_EQZ, Opcode.INVOKE_STATIC,
Opcode.INVOKE_VIRTUAL, Opcode.MOVE_RESULT_OBJECT,
Opcode.MOVE_RESULT, Opcode.IGET_WIDE,
Opcode.IF_EQZ, Opcode.IGET_WIDE,
Opcode.GOTO, Opcode.SUB_LONG_2ADDR
) )
) )

View file

@ -26,7 +26,10 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -20,7 +20,10 @@ import org.w3c.dom.Element
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
], ],

View file

@ -1,6 +1,8 @@
package app.revanced.patches.youtube.layout.returnyoutubedislike package app.revanced.patches.youtube.layout.returnyoutubedislike
import app.revanced.extensions.exception import app.revanced.extensions.exception
import app.revanced.extensions.getReference
import app.revanced.extensions.indexOfFirstInstruction
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.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
@ -9,6 +11,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.* import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.*
@ -20,6 +23,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Patch( @Patch(
name = "Return YouTube Dislike", name = "Return YouTube Dislike",
@ -32,7 +36,13 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
PlayerTypeHookPatch::class, PlayerTypeHookPatch::class,
], ],
compatiblePackages = [ compatiblePackages = [
CompatiblePackage("com.google.android.youtube", ["18.37.36", "18.38.44"]) CompatiblePackage(
"com.google.android.youtube", [
"18.43.45",
"18.44.41",
"18.45.41"
]
)
] ]
) )
@Suppress("unused") @Suppress("unused")
@ -44,6 +54,8 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
LikeFingerprint, LikeFingerprint,
DislikeFingerprint, DislikeFingerprint,
RemoveLikeFingerprint, RemoveLikeFingerprint,
RollingNumberSetterFingerprint,
RollingNumberTextViewFingerprint
) )
) { ) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = private const val INTEGRATIONS_CLASS_DESCRIPTOR =
@ -138,7 +150,77 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
// endregion // endregion
// region Hook for non litho Short videos. // region Hook rolling numbers.
RollingNumberSetterFingerprint.result?.let {
val dislikesIndex = it.scanResult.patternScanResult!!.endIndex
it.mutableMethod.apply {
val insertIndex = 1
val charSequenceInstanceRegister =
getInstruction<OneRegisterInstruction>(0).registerA
val charSequenceFieldReference =
getInstruction<ReferenceInstruction>(dislikesIndex).reference.toString()
val registerCount = implementation!!.registerCount
// This register is being overwritten, so it is free to use.
val freeRegister = registerCount - 1
val conversionContextRegister = registerCount - parameters.size + 1
addInstructions(
insertIndex,
"""
iget-object v$freeRegister, v$charSequenceInstanceRegister, $charSequenceFieldReference
invoke-static {v$conversionContextRegister, v$freeRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onRollingNumberLoaded(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String;
move-result-object v$freeRegister
iput-object v$freeRegister, v$charSequenceInstanceRegister, $charSequenceFieldReference
"""
)
}
} ?: throw RollingNumberSetterFingerprint.exception
// The rolling number Span is missing styling since it's initially set as a String.
// Modify the UI text view and use the styled like/dislike Span.
RollingNumberTextViewFingerprint.result?.let {
// Initial TextView is set in this method.
val initiallyCreatedTextViewMethod = it.mutableMethod
// Videos less than 24 hours after uploaded, like counts will be updated in real time.
// Whenever like counts are updated, TextView is set in this method.
val realTimeUpdateTextViewMethod = it.mutableClass.methods.find { method ->
method.parameterTypes.first() == "Landroid/graphics/Bitmap;"
} ?: throw PatchException("Failed to find realTimeUpdateTextViewMethod")
arrayOf(
initiallyCreatedTextViewMethod,
realTimeUpdateTextViewMethod
).forEach { insertMethod ->
insertMethod.apply {
val setTextIndex = indexOfFirstInstruction {
getReference<MethodReference>()?.name == "setText"
}
val textViewRegister =
getInstruction<FiveRegisterInstruction>(setTextIndex).registerC
val textSpanRegister =
getInstruction<FiveRegisterInstruction>(setTextIndex).registerD
addInstructions(
setTextIndex,
"""
invoke-static {v$textViewRegister, v$textSpanRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->updateRollingNumber(Landroid/widget/TextView;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
move-result-object v$textSpanRegister
"""
)
}
}
} ?: throw RollingNumberTextViewFingerprint.exception
// endregion
// region Hook for non-litho Short videos.
ShortsTextViewFingerprint.result?.let { ShortsTextViewFingerprint.result?.let {
it.mutableMethod.apply { it.mutableMethod.apply {
@ -167,7 +249,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
move-result v0 move-result v0
if-eqz v0, :ryd_disabled if-eqz v0, :ryd_disabled
return-void return-void
:is_like :is_like
:ryd_disabled :ryd_disabled
nop nop

View file

@ -0,0 +1,12 @@
package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
object RollingNumberSetterFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.INVOKE_DIRECT,
Opcode.IGET_OBJECT
),
strings = listOf("RollingNumberType required properties missing! Need updateCount, fontName, color and fontSize.")
)

View file

@ -0,0 +1,23 @@
package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object RollingNumberTextViewFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("L", "F", "F"),
opcodes = listOf(
Opcode.IPUT,
null, // invoke-direct or invoke-virtual
Opcode.IPUT_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.RETURN_VOID
),
customFingerprint = custom@{ _, classDef ->
classDef.superclass == "Landroid/support/v7/widget/AppCompatTextView;"
}
)

View file

@ -12,7 +12,7 @@ object ShortsTextViewFingerprint : MethodFingerprint(
opcodes = listOf( opcodes = listOf(
Opcode.INVOKE_SUPER, // first instruction of method Opcode.INVOKE_SUPER, // first instruction of method
Opcode.IF_NEZ, Opcode.IF_NEZ,
Opcode.RETURN_VOID, null,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST, Opcode.CHECK_CAST,

View file

@ -18,7 +18,7 @@ object TextComponentAtomicReferenceFingerprint : MethodFingerprint(
Opcode.MOVE_OBJECT_FROM16, Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16, Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16, Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16, null,
Opcode.INVOKE_VIRTUAL, // Register C is atomic reference Opcode.INVOKE_VIRTUAL, // Register C is atomic reference
Opcode.MOVE_RESULT_OBJECT, // Register A is char sequence Opcode.MOVE_RESULT_OBJECT, // Register A is char sequence
Opcode.CHECK_CAST, Opcode.CHECK_CAST,

View file

@ -21,6 +21,7 @@ object TextComponentContextFingerprint : MethodFingerprint(
Opcode.IGET_OBJECT, Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT, Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT, Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT, // conversion context field name Opcode.IGET_OBJECT, // conversion context field name
) )
) )

View file

@ -29,7 +29,9 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.45.41"
] ]
) )
] ]
@ -69,7 +71,7 @@ object WideSearchbarPatch : BytecodePatch(
* @param fromFingerprint The fingerprint to walk the method on. * @param fromFingerprint The fingerprint to walk the method on.
* @return The [MutableMethod] which was walked on. * @return The [MutableMethod] which was walked on.
*/ */
fun BytecodeContext.walkMutable(index: Int, fromFingerprint: MethodFingerprint) = private fun BytecodeContext.walkMutable(index: Int, fromFingerprint: MethodFingerprint) =
fromFingerprint.result?.let { fromFingerprint.result?.let {
toMethodWalker(it.method).nextMethod(index, true).getMethod() as MutableMethod toMethodWalker(it.method).nextMethod(index, true).getMethod() as MutableMethod
} ?: throw fromFingerprint.exception } ?: throw fromFingerprint.exception
@ -78,7 +80,7 @@ object WideSearchbarPatch : BytecodePatch(
/** /**
* Injects instructions required for certain methods. * Injects instructions required for certain methods.
*/ */
fun MutableMethod.injectSearchBarHook() { private fun MutableMethod.injectSearchBarHook() {
addInstructions( addInstructions(
implementation!!.instructions.size - 1, implementation!!.instructions.size - 1,
""" """

View file

@ -9,56 +9,59 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
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.seekbar.fingerprints.EnableNewSeekbarThumbnailsFingerprint import app.revanced.patches.youtube.layout.seekbar.fingerprints.FullscreenSeekbarThumbnailsFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Patch( @Patch(
name = "Enable old seekbar thumbnails", name = "Restore old seekbar thumbnails",
description = "Enables the old seekbar thumbnails that appear above the seekbar instead of in fullscreen.", description = "Restores the old seekbar thumbnails that appear above the seekbar instead of fullscreen thumbnails.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class], dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [ compatiblePackages = [
CompatiblePackage( CompatiblePackage(
"com.google.android.youtube", [ "com.google.android.youtube", [
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]
) )
@Suppress("unused") @Suppress("unused")
object EnableOldSeekbarThumbnailsPatch : BytecodePatch( object RestoreOldSeekbarThumbnailsPatch : BytecodePatch(
setOf(EnableNewSeekbarThumbnailsFingerprint) setOf(FullscreenSeekbarThumbnailsFingerprint)
) { ) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/EnableOldSeekbarThumbnailsPatch;" "Lapp/revanced/integrations/patches/RestoreOldSeekbarThumbnailsPatch;"
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
SwitchPreference( SwitchPreference(
"revanced_enable_old_seekbar_thumbnails", "revanced_restore_old_seekbar_thumbnails",
StringResource( StringResource(
"revanced_enable_old_seekbar_thumbnails_title", "revanced_restore_old_seekbar_thumbnails_title",
"Enable old seekbar thumbnails" "Restore old seekbar thumbnails"
), ),
StringResource( StringResource(
"revanced_enable_old_seekbar_thumbnails_summary_on", "revanced_restore_old_seekbar_thumbnails_summary_on",
"Seekbar thumbnails will appear above the seekbar" "Seekbar thumbnails will appear above the seekbar"
), ),
StringResource( StringResource(
"revanced_enable_old_seekbar_thumbnails_summary_off", "revanced_restore_old_seekbar_thumbnails_summary_off",
"Seekbar thumbnails will appear in fullscreen" "Seekbar thumbnails will appear in fullscreen"
), ),
) )
) )
EnableNewSeekbarThumbnailsFingerprint.result?.mutableMethod?.apply { FullscreenSeekbarThumbnailsFingerprint.result?.mutableMethod?.apply {
val moveResultIndex = getInstructions().lastIndex - 1 val moveResultIndex = getInstructions().lastIndex - 1
addInstruction( addInstruction(
moveResultIndex, moveResultIndex,
"invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->enableOldSeekbarThumbnails()Z" "invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->useFullscreenSeekbarThumbnails()Z"
) )
} ?: throw EnableNewSeekbarThumbnailsFingerprint.exception } ?: throw FullscreenSeekbarThumbnailsFingerprint.exception
} }
} }

View file

@ -22,8 +22,12 @@ object SeekbarPreferencesPatch : ResourcePatch(), Closeable {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
PreferenceScreen( PreferenceScreen(
"revanced_seekbar_preference_screen", "revanced_seekbar_preference_screen",
StringResource("revanced_seekbar_preference_screen_title", "Seekbar settings"), StringResource("revanced_seekbar_preference_screen_title", "Seekbar"),
seekbarPreferences seekbarPreferences,
StringResource(
"revanced_seekbar_preference_screen_summary",
"Settings for the seekbar."
)
) )
) )
} }

View file

@ -4,7 +4,7 @@ import app.revanced.patcher.extensions.or
import app.revanced.util.patch.LiteralValueFingerprint import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
object EnableNewSeekbarThumbnailsFingerprint : LiteralValueFingerprint( object FullscreenSeekbarThumbnailsFingerprint : LiteralValueFingerprint(
returnType = "Z", returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(), parameters = emptyList(),

View file

@ -12,7 +12,6 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.fingerprints.LayoutConstructorFingerprint import app.revanced.patches.shared.fingerprints.LayoutConstructorFingerprint
import app.revanced.patches.youtube.shared.fingerprints.SeekbarFingerprint
import app.revanced.patches.shared.fingerprints.SeekbarOnDrawFingerprint import app.revanced.patches.shared.fingerprints.SeekbarOnDrawFingerprint
import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.youtube.layout.sponsorblock.fingerprints.AppendTimeFingerprint import app.revanced.patches.youtube.layout.sponsorblock.fingerprints.AppendTimeFingerprint
@ -23,6 +22,7 @@ import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatParen
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.playercontrols.PlayerControlsBytecodePatch import app.revanced.patches.youtube.misc.playercontrols.PlayerControlsBytecodePatch
import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
import app.revanced.patches.youtube.shared.fingerprints.SeekbarFingerprint
import app.revanced.patches.youtube.video.information.VideoInformationPatch import app.revanced.patches.youtube.video.information.VideoInformationPatch
import app.revanced.patches.youtube.video.videoid.VideoIdPatch import app.revanced.patches.youtube.video.videoid.VideoIdPatch
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
@ -45,7 +45,10 @@ import com.android.tools.smali.dexlib2.iface.reference.StringReference
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
], ],

View file

@ -30,7 +30,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -1,5 +1,6 @@
package app.revanced.patches.youtube.layout.startupshortsreset package app.revanced.patches.youtube.layout.startupshortsreset
import app.revanced.extensions.exception
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
@ -12,8 +13,8 @@ import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Patch( @Patch(
name = "Disable Shorts on startup", name = "Disable resuming Shorts on startup",
description = "Disables playing YouTube Shorts when launching YouTube.", description = "Disables resuming the Shorts player on app startup if a Short was last opened.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class], dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [ compatiblePackages = [
CompatiblePackage( CompatiblePackage(
@ -25,39 +26,46 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]
) )
@Suppress("unused") @Suppress("unused")
object DisableShortsOnStartupPatch : BytecodePatch( object DisableResumingShortsOnStartupPatch : BytecodePatch(
setOf(UserWasInShortsFingerprint) setOf(UserWasInShortsFingerprint)
) { ) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/DisableResumingStartupShortsPlayerPatch;"
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
SwitchPreference( SwitchPreference(
"revanced_disable_resuming_shorts_player", "revanced_disable_resuming_shorts_player",
StringResource("revanced_disable_resuming_shorts_player_title", "Disable Shorts player at app startup"), StringResource("revanced_disable_resuming_shorts_player_title", "Disable resuming Shorts player"),
StringResource("revanced_disable_resuming_shorts_player_summary_on", "Shorts player is disabled at app startup"), StringResource("revanced_disable_resuming_shorts_player_summary_on", "Shorts player will not resume on app startup"),
StringResource("revanced_disable_resuming_shorts_player_summary_off", "Shorts player is enabled at app startup") StringResource("revanced_disable_resuming_shorts_player_summary_off", "Shorts player will resume on app startup")
) )
) )
val userWasInShortsResult = UserWasInShortsFingerprint.result!! UserWasInShortsFingerprint.result?.apply {
val userWasInShortsMethod = userWasInShortsResult.mutableMethod val moveResultIndex = scanResult.patternScanResult!!.endIndex
val moveResultIndex = userWasInShortsResult.scanResult.patternScanResult!!.endIndex
userWasInShortsMethod.addInstructionsWithLabels( mutableMethod.addInstructionsWithLabels(
moveResultIndex + 1, moveResultIndex + 1,
""" """
invoke-static { }, Lapp/revanced/integrations/patches/DisableStartupShortsPlayerPatch;->disableStartupShortsPlayer()Z invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z
move-result v5 move-result v5
if-eqz v5, :disable_shorts_player if-eqz v5, :disable_shorts_player
return-void return-void
:disable_shorts_player :disable_shorts_player
nop nop
""" """
) )
} ?: throw UserWasInShortsFingerprint.exception
} }
} }

View file

@ -34,7 +34,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
) )
) )
] ]

View file

@ -32,7 +32,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"com.google.android.youtube", "com.google.android.youtube",
[ [
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]
@ -82,7 +85,7 @@ object ThemeBytecodePatch : BytecodePatch(
"Light red" to "#FFFFD6D6" "Light red" to "#FFFFD6D6"
), ),
title = "Light theme background color", title = "Light theme background color",
description = "Can be a hex color or a color resource reference.", description = "Can be a hex color (#AARRGGBB) or a color resource reference.",
) )
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {

View file

@ -26,7 +26,10 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -30,7 +30,10 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -21,7 +21,10 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
CompatiblePackage( CompatiblePackage(
"com.google.android.youtube", "com.google.android.youtube",
[ [
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -26,7 +26,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -18,6 +18,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.patches.youtube.video.information.VideoInformationPatch import app.revanced.patches.youtube.video.information.VideoInformationPatch
import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
@Patch( @Patch(
description = "Spoofs the signature to prevent playback issues.", description = "Spoofs the signature to prevent playback issues.",
@ -26,14 +27,19 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
PlayerTypeHookPatch::class, PlayerTypeHookPatch::class,
PlayerResponseMethodHookPatch::class, PlayerResponseMethodHookPatch::class,
VideoInformationPatch::class, VideoInformationPatch::class,
SpoofSignatureResourcePatch::class
] ]
) )
object SpoofSignaturePatch : BytecodePatch( object SpoofSignaturePatch : BytecodePatch(
setOf( setOf(
PlayerResponseModelImplFingerprint, PlayerResponseModelImplGeneralFingerprint,
StoryboardThumbnailParentFingerprint, PlayerResponseModelImplLiveStreamFingerprint,
PlayerResponseModelImplRecommendedLevel,
StoryboardRendererSpecFingerprint, StoryboardRendererSpecFingerprint,
StoryboardRendererInitFingerprint StoryboardRendererDecoderSpecFingerprint,
StoryboardRendererDecoderRecommendedLevelFingerprint,
StoryboardThumbnailParentFingerprint,
ScrubbedPreviewLayoutFingerprint,
) )
) { ) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = private const val INTEGRATIONS_CLASS_DESCRIPTOR =
@ -42,12 +48,12 @@ object SpoofSignaturePatch : BytecodePatch(
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.MISC.addPreferences( SettingsPatch.PreferenceScreen.MISC.addPreferences(
PreferenceScreen( PreferenceScreen(
key = "revanced_spoof_signature_verification", "revanced_spoof_signature_verification",
title = StringResource( StringResource(
"revanced_spoof_signature_verification_title", "revanced_spoof_signature_verification_title",
"Spoof app signature" "Spoof app signature"
), ),
preferences = listOf( listOf(
SwitchPreference( SwitchPreference(
"revanced_spoof_signature_verification_enabled", "revanced_spoof_signature_verification_enabled",
StringResource("revanced_spoof_signature_verification_enabled_title", "Spoof app signature"), StringResource("revanced_spoof_signature_verification_enabled_title", "Spoof app signature"),
@ -83,7 +89,23 @@ object SpoofSignaturePatch : BytecodePatch(
"App signature not spoofed for feed videos\\n\\n" "App signature not spoofed for feed videos\\n\\n"
+ "Feed videos will play for less than 1 minute before encountering playback issues" + "Feed videos will play for less than 1 minute before encountering playback issues"
) )
),
SwitchPreference(
"revanced_spoof_storyboard",
StringResource("revanced_spoof_storyboard_title", "Spoof storyboard"),
StringResource("revanced_spoof_storyboard_summary_on", "Storyboard spoofed"),
StringResource(
"revanced_spoof_storyboard_summary_off",
"Storyboard not spoofed\\n\\n"
+ "Side effects include:\\n"
+ "• No ambient mode\\n"
+ "• Seekbar thumbnails are hidden"
)
) )
),
StringResource(
"revanced_spoof_signature_verification_summary",
"Spoof the app signature to prevent playback issues"
) )
) )
) )
@ -94,7 +116,8 @@ object SpoofSignaturePatch : BytecodePatch(
) )
// Force the seekbar time and chapters to always show up. // Force the seekbar time and chapters to always show up.
// This is used only if the storyboard spec fetch fails, or when viewing paid videos. // This is used if the storyboard spec fetch fails, for viewing paid videos,
// or if storyboard spoofing is turned off.
StoryboardThumbnailParentFingerprint.result?.classDef?.let { classDef -> StoryboardThumbnailParentFingerprint.result?.classDef?.let { classDef ->
StoryboardThumbnailFingerprint.also { StoryboardThumbnailFingerprint.also {
it.resolve( it.resolve(
@ -124,23 +147,74 @@ object SpoofSignaturePatch : BytecodePatch(
} ?: throw StoryboardThumbnailFingerprint.exception } ?: throw StoryboardThumbnailFingerprint.exception
} }
/** // If storyboard spoofing is turned off, then hide the empty seekbar thumbnail view.
* Hook StoryBoard renderer url ScrubbedPreviewLayoutFingerprint.result?.apply {
*/ val endIndex = scanResult.patternScanResult!!.endIndex
PlayerResponseModelImplFingerprint.result?.let { mutableMethod.apply {
it.mutableMethod.apply { val imageViewFieldName = getInstruction<ReferenceInstruction>(endIndex).reference
val getStoryBoardIndex = it.scanResult.patternScanResult!!.endIndex
val getStoryBoardRegister = getInstruction<OneRegisterInstruction>(getStoryBoardIndex).registerA
addInstructions( addInstructions(
getStoryBoardIndex, implementation!!.instructions.lastIndex,
""" """
invoke-static { v$getStoryBoardRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getStoryboardRendererSpec(Ljava/lang/String;)Ljava/lang/String; iget-object v0, p0, $imageViewFieldName # copy imageview field to a register
move-result-object v$getStoryBoardRegister invoke-static {v0}, $INTEGRATIONS_CLASS_DESCRIPTOR->seekbarImageViewCreated(Landroid/widget/ImageView;)V
""" """
) )
} }
} ?: throw PlayerResponseModelImplFingerprint.exception } ?: throw ScrubbedPreviewLayoutFingerprint.exception
/**
* Hook StoryBoard renderer url
*/
arrayOf(
PlayerResponseModelImplGeneralFingerprint,
PlayerResponseModelImplLiveStreamFingerprint
).forEach { fingerprint ->
fingerprint.result?.let {
it.mutableMethod.apply {
val getStoryBoardIndex = it.scanResult.patternScanResult!!.endIndex
val getStoryBoardRegister =
getInstruction<OneRegisterInstruction>(getStoryBoardIndex).registerA
addInstructions(
getStoryBoardIndex,
"""
invoke-static { v$getStoryBoardRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getStoryboardRendererSpec(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$getStoryBoardRegister
"""
)
}
} ?: throw fingerprint.exception
}
// Hook recommended seekbar thumbnails quality level.
StoryboardRendererDecoderRecommendedLevelFingerprint.result?.let {
val moveOriginalRecommendedValueIndex = it.scanResult.patternScanResult!!.endIndex
val originalValueRegister = it.mutableMethod
.getInstruction<OneRegisterInstruction>(moveOriginalRecommendedValueIndex).registerA
it.mutableMethod.addInstructions(
moveOriginalRecommendedValueIndex + 1, """
invoke-static { v$originalValueRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getRecommendedLevel(I)I
move-result v$originalValueRegister
"""
)
} ?: throw StoryboardRendererDecoderRecommendedLevelFingerprint.exception
// Hook the recommended precise seeking thumbnails quality level.
PlayerResponseModelImplRecommendedLevel.result?.let {
it.mutableMethod.apply {
val moveOriginalRecommendedValueIndex = it.scanResult.patternScanResult!!.endIndex
val originalValueRegister =
getInstruction<OneRegisterInstruction>(moveOriginalRecommendedValueIndex).registerA
addInstructions(
moveOriginalRecommendedValueIndex, """
invoke-static { v$originalValueRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getRecommendedLevel(I)I
move-result v$originalValueRegister
"""
)
}
} ?: throw PlayerResponseModelImplRecommendedLevel.exception
StoryboardRendererSpecFingerprint.result?.let { StoryboardRendererSpecFingerprint.result?.let {
it.mutableMethod.apply { it.mutableMethod.apply {
@ -158,22 +232,18 @@ object SpoofSignaturePatch : BytecodePatch(
} }
} ?: throw StoryboardRendererSpecFingerprint.exception } ?: throw StoryboardRendererSpecFingerprint.exception
// Hook recommended value // Hook the seekbar thumbnail decoder and use a NULL spec for live streams.
StoryboardRendererInitFingerprint.result?.let { StoryboardRendererDecoderSpecFingerprint.result?.let {
val moveOriginalRecommendedValueIndex = it.scanResult.patternScanResult!!.endIndex val storyBoardUrlIndex = it.scanResult.patternScanResult!!.startIndex + 1
val storyboardUrlRegister =
it.mutableMethod.getInstruction<OneRegisterInstruction>(storyBoardUrlIndex).registerA
val originalValueRegister = it.mutableMethod it.mutableMethod.addInstructions(
.getInstruction<OneRegisterInstruction>(moveOriginalRecommendedValueIndex).registerA storyBoardUrlIndex + 1, """
invoke-static { v$storyboardUrlRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getStoryboardDecoderRendererSpec(Ljava/lang/String;)Ljava/lang/String;
it.mutableMethod.apply { move-result-object v$storyboardUrlRegister
addInstructions( """
moveOriginalRecommendedValueIndex + 1, )
""" } ?: throw StoryboardRendererDecoderSpecFingerprint.exception
invoke-static { v$originalValueRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getRecommendedLevel(I)I
move-result v$originalValueRegister
"""
)
}
} ?: throw StoryboardRendererInitFingerprint.exception
} }
} }

View file

@ -0,0 +1,18 @@
package app.revanced.patches.youtube.misc.fix.playback
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Patch(dependencies = [SettingsPatch::class, ResourceMappingPatch::class])
object SpoofSignatureResourcePatch : ResourcePatch() {
internal var scrubbedPreviewThumbnailResourceId: Long = -1
override fun execute(context: ResourceContext) {
scrubbedPreviewThumbnailResourceId = ResourceMappingPatch.resourceMappings.single {
it.type == "id" && it.name == "thumbnail"
}.id
}
}

View file

@ -6,7 +6,7 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
object PlayerResponseModelImplFingerprint : MethodFingerprint( object PlayerResponseModelImplGeneralFingerprint : MethodFingerprint(
returnType = "Ljava/lang/String;", returnType = "Ljava/lang/String;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(), parameters = emptyList(),

View file

@ -0,0 +1,23 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.extensions.containsWideLiteralInstructionValue
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object PlayerResponseModelImplLiveStreamFingerprint : MethodFingerprint(
returnType = "Ljava/lang/String;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),
opcodes = listOf(
Opcode.RETURN_OBJECT,
Opcode.CONST_4,
Opcode.RETURN_OBJECT
),
customFingerprint = handler@{ methodDef, _ ->
if (!methodDef.definingClass.endsWith("/PlayerResponseModelImpl;")) return@handler false
methodDef.containsWideLiteralInstructionValue(70276274)
}
)

View file

@ -0,0 +1,23 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.extensions.containsWideLiteralInstructionValue
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object PlayerResponseModelImplRecommendedLevel : MethodFingerprint(
returnType = "I",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),
opcodes = listOf(
Opcode.SGET_OBJECT,
Opcode.IGET,
Opcode.RETURN
),
customFingerprint = handler@{ methodDef, _ ->
if (!methodDef.definingClass.endsWith("/PlayerResponseModelImpl;")) return@handler false
methodDef.containsWideLiteralInstructionValue(55735497)
}
)

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.SpoofSignatureResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.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.
literalSupplier = { SpoofSignatureResourcePatch.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.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
/**
* Resolves to the same method as [StoryboardRendererDecoderSpecFingerprint].
*/
object StoryboardRendererDecoderRecommendedLevelFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"),
opcodes = listOf(
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT
),
strings = listOf("#-1#")
)

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.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
/**
* Resolves to the same method as [StoryboardRendererDecoderRecommendedLevelFingerprint].
*/
object StoryboardRendererDecoderSpecFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"),
opcodes = listOf(
Opcode.INVOKE_INTERFACE, // First instruction of the method.
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_4,
Opcode.CONST_4,
Opcode.IF_NEZ,
),
strings = listOf("#-1#")
)

View file

@ -1,15 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
object StoryboardRendererInitFingerprint : MethodFingerprint(
strings = listOf("#-1#"),
opcodes = listOf(
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT
)
)

View file

@ -10,8 +10,8 @@ import app.revanced.patcher.patch.annotation.Patch
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.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.links.fingerprints.OpenLinksDirectlyPrimaryFingerprint import app.revanced.patches.youtube.misc.links.fingerprints.ABUriParserFingerprint
import app.revanced.patches.youtube.misc.links.fingerprints.OpenLinksDirectlySecondaryFingerprint import app.revanced.patches.youtube.misc.links.fingerprints.HTTPUriParserFingerprint
import app.revanced.patches.youtube.misc.settings.SettingsPatch import app.revanced.patches.youtube.misc.settings.SettingsPatch
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@ -23,20 +23,15 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
CompatiblePackage( CompatiblePackage(
"com.google.android.youtube", "com.google.android.youtube",
[ [
"18.16.37", "18.43.45",
"18.19.35", "18.44.41",
"18.20.39", "18.45.41"
"18.23.35",
"18.29.38",
"18.32.39",
"18.37.36",
"18.38.44"
] ]
) )
] ]
) )
object BypassURLRedirectsPatch : BytecodePatch( object BypassURLRedirectsPatch : BytecodePatch(
setOf(OpenLinksDirectlyPrimaryFingerprint, OpenLinksDirectlySecondaryFingerprint) setOf(ABUriParserFingerprint, HTTPUriParserFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.MISC.addPreferences( SettingsPatch.PreferenceScreen.MISC.addPreferences(
@ -48,14 +43,14 @@ object BypassURLRedirectsPatch : BytecodePatch(
) )
) )
arrayOf( mapOf(
OpenLinksDirectlyPrimaryFingerprint, ABUriParserFingerprint to 7, // Offset to Uri.parse.
OpenLinksDirectlySecondaryFingerprint HTTPUriParserFingerprint to 0 // Offset to Uri.parse.
).map { ).map { (fingerprint, offset) ->
it.result ?: throw it.exception (fingerprint.result ?: throw fingerprint.exception) to offset
}.forEach { result -> }.forEach { (result, offset) ->
result.mutableMethod.apply { result.mutableMethod.apply {
val insertIndex = result.scanResult.patternScanResult!!.startIndex val insertIndex = result.scanResult.patternScanResult!!.startIndex + offset
val uriStringRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerC val uriStringRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerC
replaceInstruction( replaceInstruction(

View file

@ -30,7 +30,10 @@ import com.android.tools.smali.dexlib2.iface.reference.StringReference
"18.29.38", "18.29.38",
"18.32.39", "18.32.39",
"18.37.36", "18.37.36",
"18.38.44" "18.38.44",
"18.43.45",
"18.44.41",
"18.45.41"
] ]
) )
] ]

View file

@ -5,16 +5,25 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
object OpenLinksDirectlyPrimaryFingerprint : MethodFingerprint( object ABUriParserFingerprint : MethodFingerprint(
returnType = "Ljava/lang/Object", returnType = "Ljava/lang/Object",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Ljava/lang/Object"), parameters = listOf("Ljava/lang/Object"),
opcodes = listOf( opcodes = listOf(
Opcode.RETURN_OBJECT,
Opcode.CHECK_CAST,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.RETURN_OBJECT,
Opcode.CHECK_CAST,
Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.RETURN_OBJECT, Opcode.RETURN_OBJECT,
Opcode.CHECK_CAST, Opcode.CHECK_CAST
Opcode.SGET, ),
Opcode.SGET_OBJECT customFingerprint = { methodDef, classDef ->
) // This method is always called "a" because this kind of class always has a single method.
methodDef.name == "a" && classDef.methods.count() == 3
}
) )

View file

@ -5,7 +5,7 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
object OpenLinksDirectlySecondaryFingerprint : MethodFingerprint( object HTTPUriParserFingerprint : MethodFingerprint(
returnType = "Landroid/net/Uri", returnType = "Landroid/net/Uri",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("Ljava/lang/String"), parameters = listOf("Ljava/lang/String"),

Some files were not shown because too many files have changed in this diff Show more