diff --git a/.github/ISSUE_TEMPLATE/bug-issue.yml b/.github/ISSUE_TEMPLATE/bug-issue.yml
index 193df90b4..6b98f0483 100644
--- a/.github/ISSUE_TEMPLATE/bug-issue.yml
+++ b/.github/ISSUE_TEMPLATE/bug-issue.yml
@@ -1,6 +1,6 @@
name: 🐞 Bug report
description: Report a very clearly broken issue.
-title: 'bug:
'
+title: 'bug: '
labels: [bug]
body:
- type: markdown
diff --git a/.github/ISSUE_TEMPLATE/patch-request.yml b/.github/ISSUE_TEMPLATE/patch-request.yml
index 53b1373a1..35084c206 100644
--- a/.github/ISSUE_TEMPLATE/patch-request.yml
+++ b/.github/ISSUE_TEMPLATE/patch-request.yml
@@ -1,6 +1,6 @@
name: ⭐ Patch Request
description: Create a detailed patch request.
-title: 'feat(patch): '
+title: 'feat: '
labels: [patch-request]
body:
- type: textarea
@@ -24,7 +24,7 @@ body:
- type: textarea
attributes:
label: Motivation
- description: Why should your patch request should be considered? What makes it valuable to the community?
+ description: Why should your patch request be considered? What makes it valuable to the community?
validations:
required: true
- type: checkboxes
@@ -38,4 +38,4 @@ body:
- label: I have written a short but informative title.
required: true
- label: I filled out all of the requested information in this issue properly.
- required: true
\ No newline at end of file
+ required: true
diff --git a/.releaserc b/.releaserc
index 3ed71897a..c113646e4 100644
--- a/.releaserc
+++ b/.releaserc
@@ -7,7 +7,13 @@
}
],
"plugins": [
- "@semantic-release/commit-analyzer",
+ [
+ "@semantic-release/commit-analyzer", {
+ "releaseRules": [
+ { "type": "build", "scope": "revanced-patcher", "release": "patch" }
+ ]
+ }
+ ],
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"gradle-semantic-release-plugin",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a9008310a..de0df6d2d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,311 @@
+# [2.174.0-dev.41](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.40...v2.174.0-dev.41) (2023-05-24)
+
+
+### Bug Fixes
+
+* **youtube/vanced-microg-support:** depend on `client-spoof` patch ([83a4905](https://github.com/revanced/revanced-patches/commit/83a490575c60adf21db926df3013f539c6d33068))
+
+# [2.174.0-dev.40](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.39...v2.174.0-dev.40) (2023-05-23)
+
+
+### Bug Fixes
+
+* **photomath/unlock-plus:** constrain to last working version ([#2232](https://github.com/revanced/revanced-patches/issues/2232)) ([4da268e](https://github.com/revanced/revanced-patches/commit/4da268edc006ea496e3b1efd037676f1c40397da))
+
+# [2.174.0-dev.39](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.38...v2.174.0-dev.39) (2023-05-22)
+
+
+### Features
+
+* **reddit:** remove compatibility version constraints ([#2226](https://github.com/revanced/revanced-patches/issues/2226)) ([f1288e4](https://github.com/revanced/revanced-patches/commit/f1288e4bb8fb1b9f394d73fd814d97db8704b8e0))
+
+# [2.174.0-dev.38](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.37...v2.174.0-dev.38) (2023-05-21)
+
+
+### Features
+
+* **trakt:** add `unlock-pro` patch ([#2210](https://github.com/revanced/revanced-patches/issues/2210)) ([1e8dcae](https://github.com/revanced/revanced-patches/commit/1e8dcae6f540455b8698703bbded5f52fd0c6300))
+
+# [2.174.0-dev.37](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.36...v2.174.0-dev.37) (2023-05-21)
+
+
+### Features
+
+* **reddit:** add `sanitize-sharing-links` patch ([#2192](https://github.com/revanced/revanced-patches/issues/2192)) ([9593e4b](https://github.com/revanced/revanced-patches/commit/9593e4b5db604957545b4ab6747c82fb815ac08b))
+
+# [2.174.0-dev.36](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.35...v2.174.0-dev.36) (2023-05-20)
+
+
+### Bug Fixes
+
+* **twitter:** correctly resolve to integrations methods ([c655416](https://github.com/revanced/revanced-patches/commit/c655416a91f0a32cfe82b1384f5958cace891833))
+
+# [2.174.0-dev.35](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.34...v2.174.0-dev.35) (2023-05-19)
+
+
+### Bug Fixes
+
+* **youtube/minimized-playback:** update settings description ([#2191](https://github.com/revanced/revanced-patches/issues/2191)) ([a561a9a](https://github.com/revanced/revanced-patches/commit/a561a9afc233e466459546fcc8452800ec56e057))
+* **youtube/settings:** fix non functional back button in settings ([#2178](https://github.com/revanced/revanced-patches/issues/2178)) ([46da834](https://github.com/revanced/revanced-patches/commit/46da83430f69b451f971bf5e9261e9d64d1a365c))
+
+
+### Features
+
+* add capability to filter from protobuf buffer ([b738b6b](https://github.com/revanced/revanced-patches/commit/b738b6bf3506f222844ef4bca99a91f78d331391))
+* use consistent names for patches ([6347146](https://github.com/revanced/revanced-patches/commit/634714690086168e63d6aa9475893135cb58db68))
+* **youtube/copy-video-url:** add tap and hold functionality to copy video url buttons ([#2174](https://github.com/revanced/revanced-patches/issues/2174)) ([95bbf46](https://github.com/revanced/revanced-patches/commit/95bbf46e77a608bd7ba8f0073d50fef01012d4df))
+* **youtube/hide-shorts-components:** hide navigation bar ([24f376a](https://github.com/revanced/revanced-patches/commit/24f376a4b8d6bdccc32ffff0d983f22eb4940791))
+* **youtube:** add `hide-shorts-components` patch ([64868f4](https://github.com/revanced/revanced-patches/commit/64868f41be9f567cb54d9214fafbf849d08b64d2))
+* **youtube:** constrain patches to `18.16.37` ([758b300](https://github.com/revanced/revanced-patches/commit/758b3005919e11d9dd4f19bf110e9d282f8d1925))
+* **youtube:** support version `18.19.35` ([491f292](https://github.com/revanced/revanced-patches/commit/491f292182a419cb5399de768560ae4daa7c86cb))
+
+# [2.174.0-dev.34](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.33...v2.174.0-dev.34) (2023-05-16)
+
+
+### Features
+
+* **vsco:** add `unlock-pro` patch ([#2168](https://github.com/revanced/revanced-patches/issues/2168)) ([7ffd1a0](https://github.com/revanced/revanced-patches/commit/7ffd1a09a7bcf09bc7e7d5f3c8c8613ca34c8c59))
+
+# [2.174.0-dev.33](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.32...v2.174.0-dev.33) (2023-05-16)
+
+
+### Bug Fixes
+
+* **youtube/spoof-signature-verification:** adjusting summary text ([#2169](https://github.com/revanced/revanced-patches/issues/2169)) ([4ccb1ee](https://github.com/revanced/revanced-patches/commit/4ccb1ee0b988bc0ddd6a0c986975b17caa828770))
+
+# [2.174.0-dev.32](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.31...v2.174.0-dev.32) (2023-05-16)
+
+
+### Bug Fixes
+
+* **youtube/sponsorblock:** fix toast shown when scrubbing thru a paused video ([#2152](https://github.com/revanced/revanced-patches/issues/2152)) ([c6c23ff](https://github.com/revanced/revanced-patches/commit/c6c23ff0d9a18e3ef3d4b9b28ffa562a2eceb58b))
+
+
+### Features
+
+* **youtube:** add options to disable toasts on connection error ([#2159](https://github.com/revanced/revanced-patches/issues/2159)) ([99916ae](https://github.com/revanced/revanced-patches/commit/99916aefaaea3b94e94e2901d70493fdb18a3dab))
+
+# [2.174.0-dev.31](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.30...v2.174.0-dev.31) (2023-05-16)
+
+
+### Features
+
+* **candylinkvpn:** add `unlock-pro` patch ([#2157](https://github.com/revanced/revanced-patches/issues/2157)) ([7159f86](https://github.com/revanced/revanced-patches/commit/7159f867801300d4ae32937743de59421de76238))
+* **messenger:** add `disable-typing-indicator` patch ([#2115](https://github.com/revanced/revanced-patches/issues/2115)) ([5d1de4f](https://github.com/revanced/revanced-patches/commit/5d1de4f4eab83e61cfc1c4aaee74179afcb9431f))
+
+# [2.174.0-dev.30](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.29...v2.174.0-dev.30) (2023-05-16)
+
+
+### Features
+
+* **youtube/hide-filter-bar:** add `PreferenceScreen` summary ([2bba5f7](https://github.com/revanced/revanced-patches/commit/2bba5f72fae06e352d2984fea7c8cc65d38ed221))
+
+# [2.174.0-dev.29](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.28...v2.174.0-dev.29) (2023-05-16)
+
+
+### Features
+
+* **youtube/downloads:** improve patch description ([e0f6452](https://github.com/revanced/revanced-patches/commit/e0f64520d0235ea219f1965ba34b7e52ded9c1d9))
+
+# [2.174.0-dev.28](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.27...v2.174.0-dev.28) (2023-05-15)
+
+
+### Bug Fixes
+
+* **youtube:** add missing compatibility annotations for `theme` and `hide-load-more-button` ([#2150](https://github.com/revanced/revanced-patches/issues/2150)) ([78803f8](https://github.com/revanced/revanced-patches/commit/78803f8ea85684e4c69e75b676fa40bae8760957))
+
+
+### Features
+
+* **youtube:** import / export of revanced settings ([#2077](https://github.com/revanced/revanced-patches/issues/2077)) ([b59cb3e](https://github.com/revanced/revanced-patches/commit/b59cb3ed60293aaf81067ff3469863add09c6b13))
+
+# [2.174.0-dev.27](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.26...v2.174.0-dev.27) (2023-05-14)
+
+
+### Bug Fixes
+
+* **youtube/video-speed:** add compatibility annotation ([#2156](https://github.com/revanced/revanced-patches/issues/2156)) ([ffa2e5d](https://github.com/revanced/revanced-patches/commit/ffa2e5d7eb0b90bb5c7a6854bab4caf9f810d917))
+
+# [2.174.0-dev.26](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.25...v2.174.0-dev.26) (2023-05-14)
+
+
+### Bug Fixes
+
+* **youtube/return-youtube-dislikes:** fix temporarily frozen video after opening a shorts ([#2126](https://github.com/revanced/revanced-patches/issues/2126)) ([e0877e3](https://github.com/revanced/revanced-patches/commit/e0877e33814ba396e64e18a577064aa5be952413))
+
+# [2.174.0-dev.25](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.24...v2.174.0-dev.25) (2023-05-14)
+
+# [2.174.0-dev.24](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.23...v2.174.0-dev.24) (2023-05-13)
+
+
+### Features
+
+* **twitch/auto-claim-channel-points:** use correct casing for "Channel Points" ([#2138](https://github.com/revanced/revanced-patches/issues/2138)) ([76a3bf2](https://github.com/revanced/revanced-patches/commit/76a3bf23b5e5591ae635e612af07cbbd78d49f53))
+
+# [2.174.0-dev.23](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.22...v2.174.0-dev.23) (2023-05-13)
+
+
+### Bug Fixes
+
+* **youtube/custom-video-speed:** add missing class for `video-speeds` patch ([#2137](https://github.com/revanced/revanced-patches/issues/2137)) ([758ef42](https://github.com/revanced/revanced-patches/commit/758ef42f9cd36d665b1737b67bcdde22d3e3eb98))
+
+# [2.174.0-dev.22](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.21...v2.174.0-dev.22) (2023-05-12)
+
+
+### Features
+
+* **youtube:** move video settings to `Video` settings category ([#2010](https://github.com/revanced/revanced-patches/issues/2010)) ([f4b9180](https://github.com/revanced/revanced-patches/commit/f4b918075a70d1a4ed9ac7e9c1f0e0acd1c77404))
+
+# [2.174.0-dev.21](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.20...v2.174.0-dev.21) (2023-05-12)
+
+
+### Features
+
+* **twitch:** add `auto-claim-channel-points` patch ([#2131](https://github.com/revanced/revanced-patches/issues/2131)) ([80fb670](https://github.com/revanced/revanced-patches/commit/80fb6701b52a8c6c6bada5546dffe3438f0e4879))
+
+# [2.174.0-dev.20](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.19...v2.174.0-dev.20) (2023-05-12)
+
+
+### Features
+
+* **youtube:** add `hide-filter-bar` patch ([6cc5f61](https://github.com/revanced/revanced-patches/commit/6cc5f61e0712fe25cd45b137773decaf4b9bb582))
+
+# [2.174.0-dev.19](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.18...v2.174.0-dev.19) (2023-05-11)
+
+
+### Features
+
+* **youtube/video-speed:** change custom video speeds inside app settings ([#2114](https://github.com/revanced/revanced-patches/issues/2114)) ([d97815a](https://github.com/revanced/revanced-patches/commit/d97815af18e645fd0fa087db0174bcc2a771ec72))
+
+# [2.174.0-dev.18](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.17...v2.174.0-dev.18) (2023-05-11)
+
+
+### Bug Fixes
+
+* **youtube/theme:** apply custom seekbar color to video thumbnails ([#2085](https://github.com/revanced/revanced-patches/issues/2085)) ([d497027](https://github.com/revanced/revanced-patches/commit/d4970273ad10f62cd9455ef9b847c686147f7dca))
+
+# [2.174.0-dev.17](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.16...v2.174.0-dev.17) (2023-05-09)
+
+
+### Bug Fixes
+
+* **youtube/remember-video-quality:** fix default video quality/speed being applied when resuming app. ([#2112](https://github.com/revanced/revanced-patches/issues/2112)) ([f68a41c](https://github.com/revanced/revanced-patches/commit/f68a41ce9f9a78818d3f28b069e70b8c66125f53))
+
+# [2.174.0-dev.16](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.15...v2.174.0-dev.16) (2023-05-08)
+
+
+### Bug Fixes
+
+* check for opcode type `CONST` ([e5bb63c](https://github.com/revanced/revanced-patches/commit/e5bb63c7ab4427b6116de4a999be306e0f3cf12e))
+
+# [2.174.0-dev.15](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.14...v2.174.0-dev.15) (2023-05-08)
+
+
+### Features
+
+* **messenger:** add `disable-switching-emoji-to-sticker-in-message-input-field` patch ([#2099](https://github.com/revanced/revanced-patches/issues/2099)) ([ac5532a](https://github.com/revanced/revanced-patches/commit/ac5532a65c353b1964d9b7d990341fc7362e510d))
+
+# [2.174.0-dev.14](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.13...v2.174.0-dev.14) (2023-05-07)
+
+
+### Features
+
+* **youtube/hide-player-overlay:** make it toggleable in settings ([#2044](https://github.com/revanced/revanced-patches/issues/2044)) ([f693d55](https://github.com/revanced/revanced-patches/commit/f693d55caf1e0b72bb1f4c39b1eeb59436191e02))
+
+# [2.174.0-dev.13](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.12...v2.174.0-dev.13) (2023-05-07)
+
+
+### Bug Fixes
+
+* account fo breaking changes from ReVanced Patcher ([#2103](https://github.com/revanced/revanced-patches/issues/2103)) ([5be25cd](https://github.com/revanced/revanced-patches/commit/5be25cde4b34d58ced35a7edbb499477b538b748))
+
+# [2.174.0-dev.12](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.11...v2.174.0-dev.12) (2023-05-07)
+
+
+### Bug Fixes
+
+* **readme-generator:** attempt sorting versions with `FlexVer` ([#2059](https://github.com/revanced/revanced-patches/issues/2059)) ([a54c464](https://github.com/revanced/revanced-patches/commit/a54c464522fa2a6a2d2525c8cb0ec961c2cc771c))
+
+# [2.174.0-dev.11](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.10...v2.174.0-dev.11) (2023-05-07)
+
+# [2.174.0-dev.10](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.9...v2.174.0-dev.10) (2023-05-07)
+
+
+### Bug Fixes
+
+* incorrect instruction offsets ([42a5a38](https://github.com/revanced/revanced-patches/commit/42a5a387da3c53c579234a44c124ab0ba26117cb))
+* incorrect smali syntax ([4e74a80](https://github.com/revanced/revanced-patches/commit/4e74a800c311d7acb2c2ddb492b43747db8a8def))
+
+# [2.174.0-dev.9](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.8...v2.174.0-dev.9) (2023-05-07)
+
+
+### Bug Fixes
+
+* incorrect cast of instruction ([fb94a1c](https://github.com/revanced/revanced-patches/commit/fb94a1cb48e8952981e2f9146eb90ee92a517b2e))
+
+# [2.174.0-dev.8](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.7...v2.174.0-dev.8) (2023-05-07)
+
+
+### Bug Fixes
+
+* **youtube/integrations:** allow playback of embedded videos ([#2092](https://github.com/revanced/revanced-patches/issues/2092)) ([8a43d75](https://github.com/revanced/revanced-patches/commit/8a43d75e2db63c47bb9ad1b75027df0868c094e5))
+
+# [2.174.0-dev.7](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.6...v2.174.0-dev.7) (2023-05-07)
+
+
+### Features
+
+* **syncforreddit:** add `disable-ads` patch ([#2066](https://github.com/revanced/revanced-patches/issues/2066)) ([c1de5d6](https://github.com/revanced/revanced-patches/commit/c1de5d6e433263b9a17305fa1c65807921594731))
+
+# [2.174.0-dev.6](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.5...v2.174.0-dev.6) (2023-05-07)
+
+
+### Features
+
+* **youtube:** `hide-load-more-button` patch ([#2078](https://github.com/revanced/revanced-patches/issues/2078)) ([7170802](https://github.com/revanced/revanced-patches/commit/71708022a06453f6f56c19d686fc505286523391))
+
+# [2.174.0-dev.5](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.4...v2.174.0-dev.5) (2023-05-07)
+
+
+### Bug Fixes
+
+* **spotify/disable-capture-restriction:** make compatible with latest versions ([#2095](https://github.com/revanced/revanced-patches/issues/2095)) ([e48f127](https://github.com/revanced/revanced-patches/commit/e48f1278da2a9d82e70be41fa2c4c480c574816b))
+
+# [2.174.0-dev.4](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.3...v2.174.0-dev.4) (2023-05-07)
+
+
+### Bug Fixes
+
+* **youtube/theme:** move options out of dependency patch ([a953448](https://github.com/revanced/revanced-patches/commit/a95344879c2ac2cd6da8ce0273dcb05e8a35d2ec))
+
+
+### Features
+
+* improve structure of `README` ([279b193](https://github.com/revanced/revanced-patches/commit/279b193b687ad9cba44ab9c2a88d2ce06be0bbf0))
+
+# [2.174.0-dev.3](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.2...v2.174.0-dev.3) (2023-05-06)
+
+# [2.174.0-dev.2](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.1...v2.174.0-dev.2) (2023-05-03)
+
+
+### Features
+
+* **patch:** bump compatibility ([#2060](https://github.com/revanced/revanced-patches/issues/2060)) ([f86836d](https://github.com/revanced/revanced-patches/commit/f86836d6295db9eb8c59916deaa991b4d99e96be))
+
+# [2.174.0-dev.1](https://github.com/revanced/revanced-patches/compare/v2.173.1-dev.1...v2.174.0-dev.1) (2023-05-03)
+
+
+### Features
+
+* **youtube/settings:** add reset button to edit preference dialog ([#2047](https://github.com/revanced/revanced-patches/issues/2047)) ([ede765a](https://github.com/revanced/revanced-patches/commit/ede765ae3c506909ee8a99517b99b6f5f113f01a))
+
+## [2.173.1-dev.1](https://github.com/revanced/revanced-patches/compare/v2.173.0...v2.173.1-dev.1) (2023-05-03)
+
+
+### Bug Fixes
+
+* **youtube/sponsorblock:** fix skip button in wrong location when full screen and comments visible ([#2051](https://github.com/revanced/revanced-patches/issues/2051)) ([30a954c](https://github.com/revanced/revanced-patches/commit/30a954cac83a66fbb25589edc487797ea5f19986))
+
# [2.173.0](https://github.com/revanced/revanced-patches/compare/v2.172.0...v2.173.0) (2023-05-02)
diff --git a/README-template.md b/README-template.md
index f9ddf51ba..5f21d12d5 100644
--- a/README-template.md
+++ b/README-template.md
@@ -1,11 +1,13 @@
-## 🧩 Patches
+## 🧩 ReVanced Patches
-The official Patch bundle provided by ReVanced and the community.
+The official ReVanced Patches.
-> Looking for the JSON variant of this? [Click here](patches.json).
+## 📋 List of patches in this repository
{{ table }}
+> Looking for the JSON variant of this? [Click here](patches.json).
+
## 📝 JSON Format
This section explains the JSON format for the [patches.json](patches.json) file.
@@ -64,7 +66,6 @@ Example:
"description": "Enables a custom theme.",
"version": "0.0.1",
"excluded": false,
- "deprecated": false,
"options": [
{
"key": "theme",
@@ -91,7 +92,6 @@ Example:
"description": "Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).",
"version": "0.0.1",
"excluded": false,
- "deprecated": false,
"options": [
{
"key": "appName",
diff --git a/README.md b/README.md
index febfeb01f..ac0cf2280 100644
--- a/README.md
+++ b/README.md
@@ -1,67 +1,69 @@
-## 🧩 Patches
+## 🧩 ReVanced Patches
-The official Patch bundle provided by ReVanced and the community.
+The official ReVanced Patches.
-> Looking for the JSON variant of this? [Click here](patches.json).
+## 📋 List of patches in this repository
### [📦 `com.google.android.youtube`](https://play.google.com/store/apps/details?id=com.google.android.youtube)
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
-| `always-autorepeat` | Always repeats the playing video again. | 18.16.37 |
-| `client-spoof` | Spoofs a patched client to allow playback. | 18.16.37 |
-| `comments` | Hides components related to comments. | 18.16.37 |
-| `copy-video-url` | Adds buttons in player to copy video links. | 18.16.37 |
+| `always-autorepeat` | Always repeats the playing video again. | 18.19.35 |
+| `client-spoof` | Spoofs a patched client to allow playback. | 18.19.35 |
+| `comments` | Hides components related to comments. | 18.19.35 |
+| `copy-video-url` | Adds buttons in player to copy video links. | 18.19.35 |
| `custom-branding` | Changes the YouTube launcher icon and name to your choice (defaults to ReVanced). | all |
-| `custom-video-buffer` | Lets you change the buffers of videos. | 18.16.37 |
-| `custom-video-speed` | Adds more video speed options. | 18.16.37 |
-| `disable-auto-captions` | Disable forced captions from being automatically enabled. | 18.16.37 |
-| `disable-fullscreen-panels` | Disables video description and comments panel in fullscreen view. | 18.16.37 |
-| `disable-player-popup-panels` | Disables panels from appearing automatically when going into fullscreen (playlist or live chat). | 18.16.37 |
-| `disable-shorts-on-startup` | Disables playing YouTube Shorts when launching YouTube. | 18.16.37 |
+| `custom-video-buffer` | Lets you change the buffers of videos. | 18.19.35 |
+| `disable-auto-captions` | Disable forced captions from being automatically enabled. | 18.19.35 |
+| `disable-fullscreen-panels` | Disables video description and comments panel in fullscreen view. | 18.19.35 |
+| `disable-player-popup-panels` | Disables panels from appearing automatically when going into fullscreen (playlist or live chat). | 18.19.35 |
+| `disable-shorts-on-startup` | Disables playing YouTube Shorts when launching YouTube. | 18.19.35 |
| `disable-zoom-haptics` | Disables haptics when zooming. | all |
-| `downloads` | Enables downloading music and videos from YouTube. | 18.16.37 |
+| `downloads` | Adds a download button to the YouTube video player. | 18.19.35 |
| `enable-debugging` | Adds debugging options. | all |
-| `general-ads` | Removes general ads. | 18.16.37 |
-| `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | 18.16.37 |
-| `hide-album-cards` | Hides the album cards below the artist description. | 18.16.37 |
-| `hide-artist-card` | Hides the artist card below the searchbar. | 18.16.37 |
-| `hide-autoplay-button` | Hides the autoplay button in the video player. | 18.16.37 |
-| `hide-breaking-news-shelf` | Hides the breaking news shelf on the homepage tab. | 18.16.37 |
-| `hide-captions-button` | Hides the captions button on video player. | 18.16.37 |
+| `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | 18.19.35 |
+| `hide-ads` | Removes general ads. | 18.19.35 |
+| `hide-album-cards` | Hides the album cards below the artist description. | 18.19.35 |
+| `hide-artist-card` | Hides the artist card below the searchbar. | 18.19.35 |
+| `hide-autoplay-button` | Hides the autoplay button in the video player. | 18.19.35 |
+| `hide-breaking-news-shelf` | Hides the breaking news shelf on the homepage tab. | 18.19.35 |
+| `hide-captions-button` | Hides the captions button on video player. | 18.19.35 |
| `hide-cast-button` | Hides the cast button in the video player. | all |
-| `hide-crowdfunding-box` | Hides the crowdfunding box between the player and video description. | 18.16.37 |
-| `hide-email-address` | Hides the email address in the account switcher. | 18.16.37 |
-| `hide-endscreen-cards` | Hides the suggested video cards at the end of a video in fullscreen. | 18.16.37 |
-| `hide-floating-microphone-button` | Hides the floating microphone button which appears in search. | 18.16.37 |
-| `hide-get-premium` | Hides advertisement for YouTube Premium under the video player. | 18.16.37 |
-| `hide-info-cards` | Hides info cards in videos. | 18.16.37 |
-| `hide-player-buttons` | Adds the option to hide video player previous and next buttons. | all |
-| `hide-player-overlay` | Hides the dark player overlay when player controls are visible. | all |
-| `hide-seekbar` | Hides the seekbar. | 18.16.37 |
-| `hide-timestamp` | Hides timestamp in video player. | 18.16.37 |
-| `hide-video-action-buttons` | Adds the options to hide action buttons under a video. | 18.16.37 |
-| `hide-watch-in-vr` | Hides the option to watch in VR from the player settings flyout panel. | 18.16.37 |
-| `hide-watermark` | Hides creator's watermarks on videos. | 18.16.37 |
-| `minimized-playback` | Enables minimized and background playback. | 18.16.37 |
-| `navigation-buttons` | Adds options to hide or change navigation buttons. | 18.16.37 |
-| `old-quality-layout` | Enables the original video quality flyout in the video player settings | 18.16.37 |
-| `open-links-externally` | Open links outside of the app directly in your browser. | 18.16.37 |
+| `hide-crowdfunding-box` | Hides the crowdfunding box between the player and video description. | 18.19.35 |
+| `hide-email-address` | Hides the email address in the account switcher. | 18.19.35 |
+| `hide-endscreen-cards` | Hides the suggested video cards at the end of a video in fullscreen. | 18.19.35 |
+| `hide-filter-bar` | Hides the filter bar in video feeds. | 18.19.35 |
+| `hide-floating-microphone-button` | Hides the floating microphone button which appears in search. | 18.19.35 |
+| `hide-get-premium` | Hides advertisement for YouTube Premium under the video player. | 18.19.35 |
+| `hide-info-cards` | Hides info cards in videos. | 18.19.35 |
+| `hide-load-more-button` | Hides the button under videos that loads similar videos. | 18.19.35 |
+| `hide-player-buttons` | Adds the option to hide video player previous and next buttons. | 18.19.35 |
+| `hide-player-overlay` | Hides the dark background overlay from the player when player controls are visible. | all |
+| `hide-seekbar` | Hides the seekbar. | 18.19.35 |
+| `hide-shorts-components` | Hides components from YouTube Shorts. | 18.19.35 |
+| `hide-timestamp` | Hides timestamp in video player. | 18.19.35 |
+| `hide-video-action-buttons` | Adds the options to hide action buttons under a video. | 18.19.35 |
+| `hide-watch-in-vr` | Hides the option to watch in VR from the player settings flyout panel. | 18.19.35 |
+| `hide-watermark` | Hides creator's watermarks on videos. | 18.19.35 |
+| `minimized-playback` | Enables minimized and background playback. | 18.19.35 |
+| `navigation-buttons` | Adds options to hide or change navigation buttons. | 18.19.35 |
+| `old-quality-layout` | Enables the original video quality flyout in the video player settings. | 18.19.35 |
+| `open-links-externally` | Open links outside of the app directly in your browser. | 18.19.35 |
| `premium-heading` | Shows premium branding on the home screen. | all |
-| `remember-playback-speed` | Adds the ability to remember the playback speed you chose in the video playback speed flyout. | 18.16.37 |
-| `remember-video-quality` | Adds the ability to remember the video quality you chose in the video quality flyout. | 18.16.37 |
-| `remove-player-button-background` | Removes the background from the video player buttons. | 18.16.37 |
-| `return-youtube-dislike` | Shows the dislike count of videos using the Return YouTube Dislike API. | 18.16.37 |
-| `seekbar-tapping` | Enables tap-to-seek on the seekbar of the video player. | 18.16.37 |
-| `sponsorblock` | Integrates SponsorBlock which allows skipping video segments such as sponsored content. | 18.16.37 |
-| `spoof-app-version` | Tricks YouTube into thinking, you are running an older version of the app. One of the side effects also includes restoring the old UI. | 18.16.37 |
-| `swipe-controls` | Adds volume and brightness swipe controls. | 18.16.37 |
-| `tablet-mini-player` | Enables the tablet mini player layout. | 18.16.37 |
+| `remember-video-quality` | Adds the ability to remember the video quality you chose in the video quality flyout. | 18.19.35 |
+| `remove-player-button-background` | Removes the background from the video player buttons. | 18.19.35 |
+| `return-youtube-dislike` | Shows the dislike count of videos using the Return YouTube Dislike API. | 18.19.35 |
+| `seekbar-tapping` | Enables tap-to-seek on the seekbar of the video player. | 18.19.35 |
+| `sponsorblock` | Integrates SponsorBlock which allows skipping video segments such as sponsored content. | 18.19.35 |
+| `spoof-app-version` | Tricks YouTube into thinking, you are running an older version of the app. One of the side effects also includes restoring the old UI. | 18.19.35 |
+| `swipe-controls` | Adds volume and brightness swipe controls. | 18.19.35 |
+| `tablet-mini-player` | Enables the tablet mini player layout. | 18.19.35 |
| `theme` | Applies a custom theme. | all |
-| `vanced-microg-support` | Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG. | 18.16.37 |
-| `video-ads` | Removes ads in the video player. | 18.16.37 |
-| `wide-searchbar` | Replaces the search icon with a wide search bar. This will hide the YouTube logo when active. | 18.16.37 |
+| `vanced-microg-support` | Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG. | 18.19.35 |
+| `video-ads` | Removes ads in the video player. | 18.19.35 |
+| `video-speed` | Adds custom video speeds and ability to remember the playback speed you chose in the video playback speed flyout. | 18.19.35 |
+| `wide-searchbar` | Replaces the search icon with a wide search bar. This will hide the YouTube logo when active. | 18.19.35 |
### [📦 `com.google.android.apps.youtube.music`](https://play.google.com/store/apps/details?id=com.google.android.apps.youtube.music)
@@ -119,6 +121,7 @@ The official Patch bundle provided by ReVanced and the community.
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
+| `auto-claim-channel-points` | Automatically claim Channel Points. | all |
| `block-audio-ads` | Blocks audio ads in streams and VODs. | 14.6.1 |
| `block-embedded-ads` | Blocks embedded stream ads using services like TTV.lol or PurpleAdBlocker. | 14.6.1 |
| `block-video-ads` | Blocks video ads in streams and VODs. | 14.6.1 |
@@ -138,6 +141,17 @@ The official Patch bundle provided by ReVanced and the community.
| `hide-views-stats` | Hides the view stats under tweets. | 9.71.0-release.0 |
+### [📦 `com.reddit.frontpage`](https://play.google.com/store/apps/details?id=com.reddit.frontpage)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `hide-ads` | Removes general ads from the Reddit frontpage and subreddits. | all |
+| `hide-subreddit-banner` | Hides banner ads from comments on subreddits. | all |
+| `premium-icon-reddit` | Unlocks premium Reddit app icons. | all |
+| `sanitize-sharing-links` | Removes (tracking) query parameters from the URLs when sharing links. | all |
+
+
### [📦 `com.spotify.music`](https://play.google.com/store/apps/details?id=com.spotify.music)
@@ -148,14 +162,14 @@ The official Patch bundle provided by ReVanced and the community.
| `spotify-theme` | Applies a custom theme. | all |
-### [📦 `com.reddit.frontpage`](https://play.google.com/store/apps/details?id=com.reddit.frontpage)
+### [📦 `com.facebook.orca`](https://play.google.com/store/apps/details?id=com.facebook.orca)
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
-| `general-reddit-ads` | Removes general ads from the Reddit frontpage and subreddits. | 2023.12.0 |
-| `hide-subreddit-banner` | Hides banner ads from comments on subreddits. | 2023.12.0 |
-| `premium-icon-reddit` | Unlocks premium Reddit app icons. | all |
+| `disable-switching-emoji-to-sticker-in-message-input-field` | Disables switching from emoji to sticker search mode in message input field | all |
+| `disable-typing-indicator` | Disables the indicator while typing a message | all |
+| `hide-inbox-ads` | Hides ads in inbox. | all |
### [📦 `at.gv.bmf.bmf2go`](https://play.google.com/store/apps/details?id=at.gv.bmf.bmf2go)
@@ -176,6 +190,14 @@ The official Patch bundle provided by ReVanced and the community.
| `spoof-signature` | Spoofs the signature of the app. | all |
+### [📦 `com.laurencedawson.reddit_sync`](https://play.google.com/store/apps/details?id=com.laurencedawson.reddit_sync)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `disable-ads` | Disables ads. | all |
+
+
### [📦 `com.myprog.hexedit`](https://play.google.com/store/apps/details?id=com.myprog.hexedit)
@@ -208,14 +230,6 @@ The official Patch bundle provided by ReVanced and the community.
| `hide-ads` | Removes general ads. | all |
-### [📦 `com.facebook.orca`](https://play.google.com/store/apps/details?id=com.facebook.orca)
-
-
-| 💊 Patch | 📜 Description | 🏹 Target Version |
-|:--------:|:--------------:|:-----------------:|
-| `hide-inbox-ads` | Hides ads in inbox. | all |
-
-
### [📦 `com.instagram.android`](https://play.google.com/store/apps/details?id=com.instagram.android)
@@ -285,7 +299,7 @@ The official Patch bundle provided by ReVanced and the community.
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
-| `unlock-plus` | Unlocks plus features. | 8.9.0 |
+| `unlock-plus` | Unlocks plus features. | 8.20.0 |
### [📦 `io.yuka.android`](https://play.google.com/store/apps/details?id=io.yuka.android)
@@ -304,30 +318,6 @@ The official Patch bundle provided by ReVanced and the community.
| `unlock-prime` | Unlocks Nova Prime and all functions of the app. | all |
-### [📦 `co.windyapp.android`](https://play.google.com/store/apps/details?id=co.windyapp.android)
-
-
-| 💊 Patch | 📜 Description | 🏹 Target Version |
-|:--------:|:--------------:|:-----------------:|
-| `unlock-pro` | Unlocks all pro features. | all |
-
-
-### [📦 `org.totschnig.myexpenses`](https://play.google.com/store/apps/details?id=org.totschnig.myexpenses)
-
-
-| 💊 Patch | 📜 Description | 🏹 Target Version |
-|:--------:|:--------------:|:-----------------:|
-| `unlock-pro` | Unlocks all professional features. | 3.4.9 |
-
-
-### [📦 `com.zombodroid.MemeGenerator`](https://play.google.com/store/apps/details?id=com.zombodroid.MemeGenerator)
-
-
-| 💊 Patch | 📜 Description | 🏹 Target Version |
-|:--------:|:--------------:|:-----------------:|
-| `unlock-pro` | Unlocks pro features. | 4.6364 |
-
-
### [📦 `com.ithebk.expensemanager`](https://play.google.com/store/apps/details?id=com.ithebk.expensemanager)
@@ -336,6 +326,14 @@ The official Patch bundle provided by ReVanced and the community.
| `unlock-pro` | Unlocks pro features. | all |
+### [📦 `com.awedea.nyx`](https://play.google.com/store/apps/details?id=com.awedea.nyx)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `unlock-pro` | Unlocks all pro features. | all |
+
+
### [📦 `ginlemon.iconpackstudio`](https://play.google.com/store/apps/details?id=ginlemon.iconpackstudio)
@@ -344,7 +342,15 @@ The official Patch bundle provided by ReVanced and the community.
| `unlock-pro` | Unlocks all pro features. | all |
-### [📦 `com.awedea.nyx`](https://play.google.com/store/apps/details?id=com.awedea.nyx)
+### [📦 `tv.trakt.trakt`](https://play.google.com/store/apps/details?id=tv.trakt.trakt)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `unlock-pro` | Unlocks pro features. | all |
+
+
+### [📦 `co.windyapp.android`](https://play.google.com/store/apps/details?id=co.windyapp.android)
| 💊 Patch | 📜 Description | 🏹 Target Version |
@@ -352,6 +358,38 @@ The official Patch bundle provided by ReVanced and the community.
| `unlock-pro` | Unlocks all pro features. | all |
+### [📦 `com.zombodroid.MemeGenerator`](https://play.google.com/store/apps/details?id=com.zombodroid.MemeGenerator)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `unlock-pro` | Unlocks pro features. | 4.6377 |
+
+
+### [📦 `com.candylink.openvpn`](https://play.google.com/store/apps/details?id=com.candylink.openvpn)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `unlock-pro` | Unlocks premium features. | all |
+
+
+### [📦 `org.totschnig.myexpenses`](https://play.google.com/store/apps/details?id=org.totschnig.myexpenses)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `unlock-pro` | Unlocks all professional features. | 3.4.9 |
+
+
+### [📦 `com.vsco.cam`](https://play.google.com/store/apps/details?id=com.vsco.cam)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `unlock-pro` | Unlocks pro features. | all |
+
+
### [📦 `com.ticktick.task`](https://play.google.com/store/apps/details?id=com.ticktick.task)
@@ -370,6 +408,8 @@ The official Patch bundle provided by ReVanced and the community.
+> Looking for the JSON variant of this? [Click here](patches.json).
+
## 📝 JSON Format
This section explains the JSON format for the [patches.json](patches.json) file.
@@ -428,7 +468,6 @@ Example:
"description": "Enables a custom theme.",
"version": "0.0.1",
"excluded": false,
- "deprecated": false,
"options": [
{
"key": "theme",
@@ -455,7 +494,6 @@ Example:
"description": "Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).",
"version": "0.0.1",
"excluded": false,
- "deprecated": false,
"options": [
{
"key": "appName",
diff --git a/build.gradle.kts b/build.gradle.kts
index dff3d309d..722156d50 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -17,13 +17,26 @@ repositories {
password = githubPassword
}
}
+ // Required for FlexVer-Java
+ maven {
+ url = uri("https://repo.sleeping.town")
+ content {
+ includeGroup("com.unascribed")
+ }
+ }
}
dependencies {
- implementation("app.revanced:revanced-patcher:7.0.0")
+ implementation("app.revanced:revanced-patcher:9.0.0")
implementation("app.revanced:multidexlib2:2.5.3-a3836654")
// Required for meta
implementation("com.google.code.gson:gson:2.10.1")
+ // Required for FlexVer-Java
+ implementation("com.unascribed:flexver-java:1.0.2")
+}
+
+kotlin {
+ jvmToolchain(11)
}
tasks {
diff --git a/gradle.properties b/gradle.properties
index 20e8bde3c..1b7355b38 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,2 +1,2 @@
kotlin.code.style = official
-version = 2.173.0
+version = 2.174.0-dev.41
diff --git a/patches.json b/patches.json
index 6bb9acbaa..f275f8b6a 100644
--- a/patches.json
+++ b/patches.json
@@ -1 +1 @@
-[{"name":"always-autorepeat","description":"Always repeats the playing video again.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"background-play","description":"Enables playing music in the background.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"block-audio-ads","description":"Blocks audio ads in streams and VODs.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":["14.3.3","14.4.0","14.5.0","14.5.2","14.6.0","14.6.1"]}]},{"name":"block-embedded-ads","description":"Blocks embedded stream ads using services like TTV.lol or PurpleAdBlocker.","version":"0.0.1","excluded":false,"options":[],"dependencies":["block-video-ads","integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":["14.3.3","14.4.0","14.5.0","14.5.2","14.6.0","14.6.1"]}]},{"name":"block-video-ads","description":"Blocks video ads in streams and VODs.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":["14.3.3","14.4.0","14.5.0","14.5.2","14.6.0","14.6.1"]}]},{"name":"bypass-certificate-checks","description":"Bypasses certificate checks which prevent YouTube Music from working on Android Auto.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["5.14.53","5.16.51","5.17.51","5.21.52","5.22.54","5.23.50","5.25.51","5.25.52","5.26.52","5.27.51","5.28.52","5.29.52","5.31.50","5.34.51","5.36.51","5.38.53","5.39.52","5.40.51","5.41.50","5.48.52"]}]},{"name":"change-package-name","description":"Changes the package name.","version":"0.0.1","excluded":true,"options":[{"key":"packageName","title":"Package name","description":"The name of the package to rename of the app.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[]},{"name":"client-spoof","description":"Spoofs a patched client to allow playback.","version":"0.0.1","excluded":false,"options":[],"dependencies":["spoof-signature-verification"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"codecs-unlock","description":"Adds more audio codec options. The new audio codecs usually result in better audio quality.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"comments","description":"Hides components related to comments.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","comments-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"compact-header","description":"Hides the music category bar at the top of the homepage.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"copy-video-url","description":"Adds buttons in player to copy video links.","version":"0.0.1","excluded":false,"options":[],"dependencies":["copy-video-url-resource","player-controls-bytecode-patch","video-information"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"custom-branding","description":"Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).","version":"0.0.1","excluded":false,"options":[{"key":"appName","title":"Application Name","description":"The name of the application it will show on your home screen.","required":true,"choices":null},{"key":"iconPath","title":"App Icon Path","description":"A path containing mipmap resource folders with icons.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"custom-video-buffer","description":"Lets you change the buffers of videos.","version":"0.0.1","excluded":true,"options":[],"dependencies":["settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"custom-video-speed","description":"Adds more video speed options.","version":"0.0.1","excluded":false,"options":[{"key":"granularity","title":"Video speed granularity","description":"The granularity of the video speeds. The higher the value, the more speeds will be available.","required":true,"choices":null},{"key":"min","title":"Minimum video speed","description":"The minimum video speed.","required":true,"choices":null},{"key":"max","title":"Maximum video speed","description":"The maximum video speed. Must be greater than the minimum video speed and smaller than 5.","required":true,"choices":null}],"dependencies":["integrations"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"debug-mode","description":"Enables Twitch\u0027s internal debugging mode.","version":"0.0.1","excluded":true,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"disable-ads","description":"Disables ads in HexEditor.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.myprog.hexedit","versions":[]}]},{"name":"disable-auto-captions","description":"Disable forced captions from being automatically enabled.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"disable-capture-restriction","description":"Allows capturing Spotify\u0027s audio output while screen sharing or screen recording.","version":"0.0.2","excluded":false,"options":[],"dependencies":["disable-capture-restriction-resource-patch"],"compatiblePackages":[{"name":"com.spotify.music","versions":[]}]},{"name":"disable-fullscreen-panels","description":"Disables video description and comments panel in fullscreen view.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"disable-login-requirement","description":"Do not force login.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"disable-player-popup-panels","description":"Disables panels from appearing automatically when going into fullscreen (playlist or live chat).","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"disable-shorts-on-startup","description":"Disables playing YouTube Shorts when launching YouTube.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"disable-zoom-haptics","description":"Disables haptics when zooming.","version":"0.0.1","excluded":false,"options":[],"dependencies":["settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"downloads","description":"Removes download restrictions and changes the default path to download to.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":["27.8.3"]},{"name":"com.zhiliaoapp.musically","versions":["27.8.3"]}]},{"name":"downloads","description":"Enables downloading music and videos from YouTube.","version":"0.0.1","excluded":false,"options":[],"dependencies":["downloads-resource-patch","player-controls-bytecode-patch","video-information"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"dynamic-color","description":"Replaces the default Twitter Blue with the users Material You palette.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.twitter.android","versions":[]}]},{"name":"enable-android-debugging","description":"Enables Android debugging capabilities.","version":"0.0.1","excluded":true,"options":[{"key":"debuggable","title":"App debugging","description":"Whether to make the app debuggable on Android.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[]},{"name":"enable-debugging","description":"Adds debugging options.","version":"0.0.2","excluded":false,"options":[],"dependencies":["integrations","settings","enable-android-debugging"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"enable-on-demand","description":"Enables listening to songs on-demand, allowing to play any song from playlists, albums or artists without limitations. This does not remove ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.spotify.lite","versions":[]}]},{"name":"exclusive-audio-playback","description":"Enables the option to play music without video.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"export-all-activities","description":"Makes all app activities exportable.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"feed-filter","description":"Filters tiktok videos: removing ads, removing livestreams.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":["27.8.3"]},{"name":"com.zhiliaoapp.musically","versions":["27.8.3"]}]},{"name":"fix-google-login","description":"Allows logging in with a Google account.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"general-ads","description":"Removes general ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":["GeneralAdsResourcePatch","VerticalScrollPatch","FixBackToExitGesturePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"general-reddit-ads","description":"Removes general ads from the Reddit frontpage and subreddits.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2021.45.0","2022.43.0","2023.05.0","2023.06.0","2023.07.0","2023.07.1","2023.08.0","2023.09.0","2023.09.1","2023.10.0","2023.11.0","2023.12.0"]}]},{"name":"hdr-auto-brightness","description":"Makes the brightness of HDR videos follow the system default.","version":"0.0.2","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"hide-ads","description":"Removes ads from Inshorts.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.nis.app","versions":[]}]},{"name":"hide-ads","description":"Removes ads from TikTok.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"hide-ads","description":"Removes general ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":["VerticalScrollPatch"],"compatiblePackages":[{"name":"com.vanced.android.youtube","versions":[]}]},{"name":"hide-ads","description":"Hides ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":["json-hook"],"compatiblePackages":[{"name":"com.twitter.android","versions":[]}]},{"name":"hide-album-cards","description":"Hides the album cards below the artist description.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","hide-album-cards-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"hide-artist-card","description":"Hides the artist card below the searchbar.","version":"0.0.1","excluded":false,"options":[],"dependencies":["resource-mapping","LithoFilterPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"hide-autoplay-button","description":"Hides the autoplay button in the video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings","resource-mapping"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"hide-breaking-news-shelf","description":"Hides the breaking news shelf on the homepage tab.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","breaking-news-shelf-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"hide-captions-button","description":"Hides the captions button on video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"hide-cast-button","description":"Hides the cast button in the video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"hide-crowdfunding-box","description":"Hides the crowdfunding box between the player and video description.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","crowdfunding-box-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"hide-email-address","description":"Hides the email address in the account switcher.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","hide-email-address-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"hide-endscreen-cards","description":"Hides the suggested video cards at the end of a video in fullscreen.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","hide-endscreen-cards-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"hide-floating-microphone-button","description":"Hides the floating microphone button which appears in search.","version":"0.0.1","excluded":false,"options":[],"dependencies":["HideFloatingMicrophoneButtonResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"hide-get-premium","description":"Removes all \"Get Premium\" evidences from the avatar menu.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["5.14.53","5.16.51","5.17.51","5.21.52","5.22.54","5.23.50","5.25.51","5.25.52","5.26.52","5.27.51","5.28.52","5.29.52","5.31.50","5.34.51","5.36.51","5.38.53","5.39.52"]}]},{"name":"hide-get-premium","description":"Hides advertisement for YouTube Premium under the video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.15.40","18.16.37"]}]},{"name":"hide-inbox-ads","description":"Hides ads in inbox.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.facebook.orca","versions":[]}]},{"name":"hide-info-cards","description":"Hides info cards in videos.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","HideInfocardsResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"hide-player-buttons","description":"Adds the option to hide video player previous and next buttons.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"hide-player-overlay","description":"Hides the dark player overlay when player controls are visible.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"hide-premium-navbar","description":"Removes the premium tab from the navbar.","version":"0.0.1","excluded":false,"options":[],"dependencies":["resource-mapping"],"compatiblePackages":[{"name":"com.spotify.music","versions":[]}]},{"name":"hide-recommended-users","description":"Hides recommended users.","version":"0.0.1","excluded":false,"options":[],"dependencies":["json-hook"],"compatiblePackages":[{"name":"com.twitter.android","versions":[]}]},{"name":"hide-seekbar","description":"Hides the seekbar.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"hide-subreddit-banner","description":"Hides banner ads from comments on subreddits.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.05.0","2023.06.0","2023.07.0","2023.07.1","2023.08.0","2023.09.0","2023.09.1","2023.10.0","2023.11.0","2023.12.0"]}]},{"name":"hide-timeline-ads","description":"Removes ads from the timeline.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.instagram.android","versions":[]}]},{"name":"hide-timestamp","description":"Hides timestamp in video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"hide-video-action-buttons","description":"Adds the options to hide action buttons under a video.","version":"0.0.1","excluded":false,"options":[],"dependencies":["resource-mapping","LithoFilterPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"hide-views-stats","description":"Hides the view stats under tweets.","version":"0.0.1","excluded":false,"options":[],"dependencies":["HideViewsBytecodePatch"],"compatiblePackages":[{"name":"com.twitter.android","versions":["9.69.1-release.0","9.71.0-release.0"]}]},{"name":"hide-watch-in-vr","description":"Hides the option to watch in VR from the player settings flyout panel.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"hide-watermark","description":"Hides creator\u0027s watermarks on videos.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"minimized-playback","description":"Enables minimized and background playback.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","player-type-hook","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"minimized-playback-music","description":"Enables minimized playback on Kids music.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"music-microg-support","description":"Allows YouTube Music ReVanced to run without root and under a different package name.","version":"0.0.2","excluded":false,"options":[],"dependencies":["music-microg-resource-patch"],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"music-video-ads","description":"Removes ads in the music player.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"navigation-buttons","description":"Adds options to hide or change navigation buttons.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings","ResolvePivotBarFingerprintsPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"old-quality-layout","description":"Enables the original video quality flyout in the video player settings","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"open-links-externally","description":"Open links outside of the app directly in your browser.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"playback-speed","description":"Enables the playback speed option for all videos.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"predictive-back-gesture","description":"Enables the predictive back gesture introduced on Android 13.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"premium-heading","description":"Shows premium branding on the home screen.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"premium-icon-reddit","description":"Unlocks premium Reddit app icons.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":[]}]},{"name":"premium-unlock","description":"Unlocks premium functions.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"org.citra.citra_emu","versions":[]},{"name":"org.citra.citra_emu.canary","versions":[]}]},{"name":"pro-unlock","description":"Unlocks pro-only functions.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.backdrops.wallpapers","versions":["4.52"]}]},{"name":"promo-code-unlock","description":"Disables the validation of promo code. Any code will work to unlock all features.","version":"0.0.1","excluded":false,"options":[],"dependencies":["spoof-cert-patch"],"compatiblePackages":[{"name":"de.dwd.warnapp","versions":[]}]},{"name":"remember-playback-speed","description":"Adds the ability to remember the playback speed you chose in the video playback speed flyout.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings","video-id-hook","video-information"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.08.37","18.15.40","18.16.37"]}]},{"name":"remember-video-quality","description":"Adds the ability to remember the video quality you chose in the video quality flyout.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","video-id-hook","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.08.37","18.15.40","18.16.37"]}]},{"name":"remove-ads","description":"Removes all ads from the app.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"net.binarymode.android.irplus","versions":[]}]},{"name":"remove-bootloader-detection","description":"Removes the check for an unlocked bootloader.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.bmf.bmf2go","versions":["2.2.0"]}]},{"name":"remove-broadcasts-restriction","description":"Enables starting/stopping NetGuard via broadcasts.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[{"name":"eu.faircode.netguard","versions":[]}]},{"name":"remove-player-button-background","description":"Removes the background from the video player buttons.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"remove-root-detection","description":"Removes the check for root permissions.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.bmf.bmf2go","versions":["2.2.0"]}]},{"name":"remove-root-detection","description":"Removes the check for root permissions and unlocked bootloader.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.oe.app","versions":[]}]},{"name":"remove-screenshot-restriction","description":"Removes the restriction of taking screenshots in apps that normally wouldn\u0027t allow it.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"return-youtube-dislike","description":"Shows the dislike count of videos using the Return YouTube Dislike API.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","video-id-hook","return-youtube-dislike-resource-patch","player-type-hook"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.15.40","18.16.37"]}]},{"name":"seekbar-tapping","description":"Enables tap-to-seek on the seekbar of the video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"settings","description":"Adds settings menu to Twitch.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings-resource-patch"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"settings","description":"Adds ReVanced settings to TikTok.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations"],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":["27.8.3"]},{"name":"com.zhiliaoapp.musically","versions":["27.8.3"]}]},{"name":"show-deleted-messages","description":"Shows deleted chat messages behind a clickable spoiler.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"show-seekbar","description":"Shows progress bar for all video.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"sim-spoof","description":"Spoofs the information which is retrieved from the sim-card.","version":"0.0.1","excluded":true,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":["27.8.3"]},{"name":"com.zhiliaoapp.musically","versions":["27.8.3"]}]},{"name":"sponsorblock","description":"Integrates SponsorBlock which allows skipping video segments such as sponsored content.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","video-id-hook","video-information","player-type-hook","player-controls-bytecode-patch","sponsorblock-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.08.37","18.15.40","18.16.37"]}]},{"name":"spoof-app-version","description":"Tricks YouTube into thinking, you are running an older version of the app. One of the side effects also includes restoring the old UI.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"spoof-signature","description":"Spoofs the signature of the app.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.oe.app","versions":[]}]},{"name":"spoof-wifi-connection","description":"Spoofs an existing Wi-Fi connection.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"spotify-theme","description":"Applies a custom theme.","version":"0.0.1","excluded":false,"options":[{"key":"backgroundColor","title":"Background color","description":"The background color. Can be a hex color or a resource reference.","required":false,"choices":null},{"key":"accentColor","title":"Accent color","description":"The accent color (\u0027spotify green\u0027 by default). Can be a hex color or a resource reference.","required":false,"choices":null},{"key":"accentPressedColor","title":"Pressed accent for the dark theme","description":"The color when accented buttons are pressed, by default slightly darker than accent. Can be a hex color or a resource reference.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[{"name":"com.spotify.music","versions":[]}]},{"name":"swipe-controls","description":"Adds volume and brightness swipe controls.","version":"0.0.3","excluded":false,"options":[],"dependencies":["integrations","player-type-hook","swipe-controls-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"tablet-mini-player","description":"Enables the tablet mini player layout.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.15.40","18.16.37"]}]},{"name":"tasteBuilder-remover","description":"Removes the \"Tell us which artists you like\" card from the home screen.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"theme","description":"Applies a custom theme.","version":"0.0.1","excluded":false,"options":[],"dependencies":["theme-litho-components","ThemeResourcePatch","integrations"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"unlock-paid-widgets","description":"Unlocks paid widgets of the app","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.dci.dev.androidtwelvewidgets","versions":[]}]},{"name":"unlock-plus","description":"Unlocks plus features.","version":"0.0.1","excluded":false,"options":[],"dependencies":["SignatureDetectionPatch"],"compatiblePackages":[{"name":"com.microblink.photomath","versions":["8.6.0","8.7.0","8.8.0","8.9.0","8.10.0","8.11.0","8.12.0","8.13.0","8.14.0","8.15.0","8.16.0","8.17.0","8.18.0","8.18.1","8.19.0","8.20.0","8.21.0"]}]},{"name":"unlock-premium","description":"Unlocks premium features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"io.yuka.android","versions":[]}]},{"name":"unlock-prime","description":"Unlocks Nova Prime and all functions of the app.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.teslacoilsw.launcher","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"co.windyapp.android","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all professional features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"org.totschnig.myexpenses","versions":["3.4.9"]}]},{"name":"unlock-pro","description":"Unlocks pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":["SignatureVerificationPatch","LicenseValidationPatch"],"compatiblePackages":[{"name":"com.zombodroid.MemeGenerator","versions":["4.6364"]}]},{"name":"unlock-pro","description":"Unlocks pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ithebk.expensemanager","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"ginlemon.iconpackstudio","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.awedea.nyx","versions":[]}]},{"name":"unlock-themes","description":"Unlocks all themes that are inaccessible until a certain level is reached.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ticktick.task","versions":[]}]},{"name":"unlock-trial","description":"Unlocks the trial version.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"net.dinglisch.android.taskerm","versions":[]}]},{"name":"upgrade-button-remover","description":"Removes the upgrade tab from the pivot bar.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"vanced-microg-support","description":"Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG.","version":"0.0.1","excluded":false,"options":[],"dependencies":["microg-resource-patch","hide-cast-button"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"video-ads","description":"Removes ads in the video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]},{"name":"wide-searchbar","description":"Replaces the search icon with a wide search bar. This will hide the YouTube logo when active.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.49.37","18.03.36","18.03.42","18.04.35","18.04.41","18.05.32","18.05.35","18.05.40","18.08.37","18.15.40","18.16.37"]}]}]
\ No newline at end of file
+[{"name":"always-autorepeat","description":"Always repeats the playing video again.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"auto-claim-channel-points","description":"Automatically claim Channel Points.","version":"0.0.1","excluded":false,"options":[],"dependencies":["settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"background-play","description":"Enables playing music in the background.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"block-audio-ads","description":"Blocks audio ads in streams and VODs.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":["14.3.3","14.4.0","14.5.0","14.5.2","14.6.0","14.6.1"]}]},{"name":"block-embedded-ads","description":"Blocks embedded stream ads using services like TTV.lol or PurpleAdBlocker.","version":"0.0.1","excluded":false,"options":[],"dependencies":["block-video-ads","integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":["14.3.3","14.4.0","14.5.0","14.5.2","14.6.0","14.6.1"]}]},{"name":"block-video-ads","description":"Blocks video ads in streams and VODs.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":["14.3.3","14.4.0","14.5.0","14.5.2","14.6.0","14.6.1"]}]},{"name":"bypass-certificate-checks","description":"Bypasses certificate checks which prevent YouTube Music from working on Android Auto.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["5.14.53","5.16.51","5.17.51","5.21.52","5.22.54","5.23.50","5.25.51","5.25.52","5.26.52","5.27.51","5.28.52","5.29.52","5.31.50","5.34.51","5.36.51","5.38.53","5.39.52","5.40.51","5.41.50","5.48.52"]}]},{"name":"change-package-name","description":"Changes the package name.","version":"0.0.1","excluded":true,"options":[{"key":"packageName","title":"Package name","description":"The name of the package to rename of the app.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[]},{"name":"client-spoof","description":"Spoofs a patched client to allow playback.","version":"0.0.1","excluded":false,"options":[],"dependencies":["spoof-signature-verification"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"codecs-unlock","description":"Adds more audio codec options. The new audio codecs usually result in better audio quality.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"comments","description":"Hides components related to comments.","version":"0.0.1","excluded":false,"options":[],"dependencies":["settings","resource-mapping"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"compact-header","description":"Hides the music category bar at the top of the homepage.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"copy-video-url","description":"Adds buttons in player to copy video links.","version":"0.0.1","excluded":false,"options":[],"dependencies":["copy-video-url-resource","player-controls-bytecode-patch","video-information"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"custom-branding","description":"Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).","version":"0.0.1","excluded":false,"options":[{"key":"appName","title":"Application Name","description":"The name of the application it will show on your home screen.","required":true,"choices":null},{"key":"iconPath","title":"App Icon Path","description":"A path containing mipmap resource folders with icons.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"custom-video-buffer","description":"Lets you change the buffers of videos.","version":"0.0.1","excluded":true,"options":[],"dependencies":["settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"debug-mode","description":"Enables Twitch\u0027s internal debugging mode.","version":"0.0.1","excluded":true,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"disable-ads","description":"Disables ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":["DisablePiracyDetectionPatch"],"compatiblePackages":[{"name":"com.laurencedawson.reddit_sync","versions":[]}]},{"name":"disable-ads","description":"Disables ads in HexEditor.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.myprog.hexedit","versions":[]}]},{"name":"disable-auto-captions","description":"Disable forced captions from being automatically enabled.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"disable-capture-restriction","description":"Allows capturing Spotify\u0027s audio output while screen sharing or screen recording.","version":"0.0.2","excluded":false,"options":[],"dependencies":["disable-capture-restriction-resource-patch"],"compatiblePackages":[{"name":"com.spotify.music","versions":[]}]},{"name":"disable-fullscreen-panels","description":"Disables video description and comments panel in fullscreen view.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"disable-login-requirement","description":"Do not force login.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"disable-player-popup-panels","description":"Disables panels from appearing automatically when going into fullscreen (playlist or live chat).","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"disable-shorts-on-startup","description":"Disables playing YouTube Shorts when launching YouTube.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"disable-switching-emoji-to-sticker-in-message-input-field","description":"Disables switching from emoji to sticker search mode in message input field","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.facebook.orca","versions":[]}]},{"name":"disable-typing-indicator","description":"Disables the indicator while typing a message","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.facebook.orca","versions":[]}]},{"name":"disable-zoom-haptics","description":"Disables haptics when zooming.","version":"0.0.1","excluded":false,"options":[],"dependencies":["settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"downloads","description":"Adds a download button to the YouTube video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["downloads-resource-patch","player-controls-bytecode-patch","video-information"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"downloads","description":"Removes download restrictions and changes the default path to download to.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":["27.8.3"]},{"name":"com.zhiliaoapp.musically","versions":["27.8.3"]}]},{"name":"dynamic-color","description":"Replaces the default Twitter Blue with the users Material You palette.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.twitter.android","versions":[]}]},{"name":"enable-android-debugging","description":"Enables Android debugging capabilities.","version":"0.0.1","excluded":true,"options":[{"key":"debuggable","title":"App debugging","description":"Whether to make the app debuggable on Android.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[]},{"name":"enable-debugging","description":"Adds debugging options.","version":"0.0.2","excluded":false,"options":[],"dependencies":["integrations","settings","enable-android-debugging"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"enable-on-demand","description":"Enables listening to songs on-demand, allowing to play any song from playlists, albums or artists without limitations. This does not remove ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.spotify.lite","versions":[]}]},{"name":"exclusive-audio-playback","description":"Enables the option to play music without video.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"export-all-activities","description":"Makes all app activities exportable.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"feed-filter","description":"Filters tiktok videos: removing ads, removing livestreams.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":["27.8.3"]},{"name":"com.zhiliaoapp.musically","versions":["27.8.3"]}]},{"name":"fix-google-login","description":"Allows logging in with a Google account.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"hdr-auto-brightness","description":"Makes the brightness of HDR videos follow the system default.","version":"0.0.2","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-ads","description":"Removes general ads from the Reddit frontpage and subreddits.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":[]}]},{"name":"hide-ads","description":"Removes general ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":["HideAdsResourcePatch","VerticalScrollPatch","FixBackToExitGesturePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-ads","description":"Removes ads from Inshorts.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.nis.app","versions":[]}]},{"name":"hide-ads","description":"Hides ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":["json-hook"],"compatiblePackages":[{"name":"com.twitter.android","versions":[]}]},{"name":"hide-ads","description":"Removes general ads.","version":"0.0.1","excluded":false,"options":[],"dependencies":["VerticalScrollPatch"],"compatiblePackages":[{"name":"com.vanced.android.youtube","versions":[]}]},{"name":"hide-ads","description":"Removes ads from TikTok.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"hide-album-cards","description":"Hides the album cards below the artist description.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","hide-album-cards-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-artist-card","description":"Hides the artist card below the searchbar.","version":"0.0.1","excluded":false,"options":[],"dependencies":["resource-mapping","LithoFilterPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-autoplay-button","description":"Hides the autoplay button in the video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings","resource-mapping"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-breaking-news-shelf","description":"Hides the breaking news shelf on the homepage tab.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","breaking-news-shelf-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-captions-button","description":"Hides the captions button on video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-cast-button","description":"Hides the cast button in the video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"hide-crowdfunding-box","description":"Hides the crowdfunding box between the player and video description.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","crowdfunding-box-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-email-address","description":"Hides the email address in the account switcher.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","hide-email-address-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-endscreen-cards","description":"Hides the suggested video cards at the end of a video in fullscreen.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","hide-endscreen-cards-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-filter-bar","description":"Hides the filter bar in video feeds.","version":"0.0.1","excluded":false,"options":[],"dependencies":["HideFilterBarResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-floating-microphone-button","description":"Hides the floating microphone button which appears in search.","version":"0.0.1","excluded":false,"options":[],"dependencies":["HideFloatingMicrophoneButtonResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-get-premium","description":"Hides advertisement for YouTube Premium under the video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-get-premium","description":"Removes all \"Get Premium\" evidences from the avatar menu.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["5.14.53","5.16.51","5.17.51","5.21.52","5.22.54","5.23.50","5.25.51","5.25.52","5.26.52","5.27.51","5.28.52","5.29.52","5.31.50","5.34.51","5.36.51","5.38.53","5.39.52"]}]},{"name":"hide-inbox-ads","description":"Hides ads in inbox.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.facebook.orca","versions":[]}]},{"name":"hide-info-cards","description":"Hides info cards in videos.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","HideInfocardsResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-load-more-button","description":"Hides the button under videos that loads similar videos.","version":"0.0.1","excluded":false,"options":[],"dependencies":["hide-load-more-button-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-player-buttons","description":"Adds the option to hide video player previous and next buttons.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-player-overlay","description":"Hides the dark background overlay from the player when player controls are visible.","version":"0.0.2","excluded":false,"options":[],"dependencies":["HidePlayerOverlayResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"hide-premium-navbar","description":"Removes the premium tab from the navbar.","version":"0.0.1","excluded":false,"options":[],"dependencies":["resource-mapping"],"compatiblePackages":[{"name":"com.spotify.music","versions":[]}]},{"name":"hide-recommended-users","description":"Hides recommended users.","version":"0.0.1","excluded":false,"options":[],"dependencies":["json-hook"],"compatiblePackages":[{"name":"com.twitter.android","versions":[]}]},{"name":"hide-seekbar","description":"Hides the seekbar.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings","SeekbarColorBytecodePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-shorts-components","description":"Hides components from YouTube Shorts.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","LithoFilterPatch","HideShortsComponentsResourcePatch","resource-mapping"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-subreddit-banner","description":"Hides banner ads from comments on subreddits.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":[]}]},{"name":"hide-timeline-ads","description":"Removes ads from the timeline.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.instagram.android","versions":[]}]},{"name":"hide-timestamp","description":"Hides timestamp in video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-video-action-buttons","description":"Adds the options to hide action buttons under a video.","version":"0.0.1","excluded":false,"options":[],"dependencies":["resource-mapping","LithoFilterPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-views-stats","description":"Hides the view stats under tweets.","version":"0.0.1","excluded":false,"options":[],"dependencies":["HideViewsBytecodePatch"],"compatiblePackages":[{"name":"com.twitter.android","versions":["9.69.1-release.0","9.71.0-release.0"]}]},{"name":"hide-watch-in-vr","description":"Hides the option to watch in VR from the player settings flyout panel.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"hide-watermark","description":"Hides creator\u0027s watermarks on videos.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"minimized-playback","description":"Enables minimized and background playback.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","player-type-hook","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"minimized-playback-music","description":"Enables minimized playback on Kids music.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"music-microg-support","description":"Allows YouTube Music ReVanced to run without root and under a different package name.","version":"0.0.2","excluded":false,"options":[],"dependencies":["music-microg-resource-patch"],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"music-video-ads","description":"Removes ads in the music player.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"navigation-buttons","description":"Adds options to hide or change navigation buttons.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings","ResolvePivotBarFingerprintsPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"old-quality-layout","description":"Enables the original video quality flyout in the video player settings.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","OldQualityLayoutResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"open-links-externally","description":"Open links outside of the app directly in your browser.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"playback-speed","description":"Enables the playback speed option for all videos.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"predictive-back-gesture","description":"Enables the predictive back gesture introduced on Android 13.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"premium-heading","description":"Shows premium branding on the home screen.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"premium-icon-reddit","description":"Unlocks premium Reddit app icons.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":[]}]},{"name":"premium-unlock","description":"Unlocks premium functions.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"org.citra.citra_emu","versions":[]},{"name":"org.citra.citra_emu.canary","versions":[]}]},{"name":"pro-unlock","description":"Unlocks pro-only functions.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.backdrops.wallpapers","versions":["4.52"]}]},{"name":"promo-code-unlock","description":"Disables the validation of promo code. Any code will work to unlock all features.","version":"0.0.1","excluded":false,"options":[],"dependencies":["spoof-cert-patch"],"compatiblePackages":[{"name":"de.dwd.warnapp","versions":[]}]},{"name":"remember-video-quality","description":"Adds the ability to remember the video quality you chose in the video quality flyout.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","video-information","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"remove-ads","description":"Removes all ads from the app.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"net.binarymode.android.irplus","versions":[]}]},{"name":"remove-bootloader-detection","description":"Removes the check for an unlocked bootloader.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.bmf.bmf2go","versions":["2.2.0"]}]},{"name":"remove-broadcasts-restriction","description":"Enables starting/stopping NetGuard via broadcasts.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[{"name":"eu.faircode.netguard","versions":[]}]},{"name":"remove-player-button-background","description":"Removes the background from the video player buttons.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"remove-root-detection","description":"Removes the check for root permissions and unlocked bootloader.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.oe.app","versions":[]}]},{"name":"remove-root-detection","description":"Removes the check for root permissions.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.bmf.bmf2go","versions":["2.2.0"]}]},{"name":"remove-screenshot-restriction","description":"Removes the restriction of taking screenshots in apps that normally wouldn\u0027t allow it.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"return-youtube-dislike","description":"Shows the dislike count of videos using the Return YouTube Dislike API.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","video-id-hook","return-youtube-dislike-resource-patch","player-type-hook"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"sanitize-sharing-links","description":"Removes (tracking) query parameters from the URLs when sharing links.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":[]}]},{"name":"seekbar-tapping","description":"Enables tap-to-seek on the seekbar of the video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","EnableSeekbarTappingResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"settings","description":"Adds settings menu to Twitch.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings-resource-patch"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"settings","description":"Adds ReVanced settings to TikTok.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations"],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":["27.8.3"]},{"name":"com.zhiliaoapp.musically","versions":["27.8.3"]}]},{"name":"show-deleted-messages","description":"Shows deleted chat messages behind a clickable spoiler.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"show-seekbar","description":"Shows progress bar for all video.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"sim-spoof","description":"Spoofs the information which is retrieved from the sim-card.","version":"0.0.1","excluded":true,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":["27.8.3"]},{"name":"com.zhiliaoapp.musically","versions":["27.8.3"]}]},{"name":"sponsorblock","description":"Integrates SponsorBlock which allows skipping video segments such as sponsored content.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","video-id-hook","video-information","player-type-hook","player-controls-bytecode-patch","sponsorblock-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"spoof-app-version","description":"Tricks YouTube into thinking, you are running an older version of the app. One of the side effects also includes restoring the old UI.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"spoof-signature","description":"Spoofs the signature of the app.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"at.gv.oe.app","versions":[]}]},{"name":"spoof-wifi-connection","description":"Spoofs an existing Wi-Fi connection.","version":"0.0.1","excluded":true,"options":[],"dependencies":[],"compatiblePackages":[]},{"name":"spotify-theme","description":"Applies a custom theme.","version":"0.0.1","excluded":false,"options":[{"key":"backgroundColor","title":"Background color","description":"The background color. Can be a hex color or a resource reference.","required":false,"choices":null},{"key":"accentColor","title":"Accent color","description":"The accent color (\u0027spotify green\u0027 by default). Can be a hex color or a resource reference.","required":false,"choices":null},{"key":"accentPressedColor","title":"Pressed accent for the dark theme","description":"The color when accented buttons are pressed, by default slightly darker than accent. Can be a hex color or a resource reference.","required":false,"choices":null}],"dependencies":[],"compatiblePackages":[{"name":"com.spotify.music","versions":[]}]},{"name":"swipe-controls","description":"Adds volume and brightness swipe controls.","version":"0.0.3","excluded":false,"options":[],"dependencies":["integrations","player-type-hook","swipe-controls-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"tablet-mini-player","description":"Enables the tablet mini player layout.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"tasteBuilder-remover","description":"Removes the \"Tell us which artists you like\" card from the home screen.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"theme","description":"Applies a custom theme.","version":"0.0.1","excluded":false,"options":[{"key":"darkThemeBackgroundColor","title":"Background color for the dark theme","description":"The background color of the dark theme. Can be a hex color or a resource reference.","required":false,"choices":null},{"key":"lightThemeBackgroundColor","title":"Background color for the light theme","description":"The background color of the light theme. Can be a hex color or a resource reference.","required":false,"choices":null},{"key":"splashScreenBackgroundColor","title":"Background color for the splash screen","description":"The background color of the splash screen. Can be a hex color or a resource reference.","required":false,"choices":null}],"dependencies":["litho-color-hook","SeekbarColorBytecodePatch","ThemeResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"unlock-paid-widgets","description":"Unlocks paid widgets of the app","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.dci.dev.androidtwelvewidgets","versions":[]}]},{"name":"unlock-plus","description":"Unlocks plus features.","version":"0.0.1","excluded":false,"options":[],"dependencies":["SignatureDetectionPatch"],"compatiblePackages":[{"name":"com.microblink.photomath","versions":["8.20.0"]}]},{"name":"unlock-premium","description":"Unlocks premium features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"io.yuka.android","versions":[]}]},{"name":"unlock-prime","description":"Unlocks Nova Prime and all functions of the app.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.teslacoilsw.launcher","versions":[]}]},{"name":"unlock-pro","description":"Unlocks pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ithebk.expensemanager","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.awedea.nyx","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"ginlemon.iconpackstudio","versions":[]}]},{"name":"unlock-pro","description":"Unlocks pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"tv.trakt.trakt","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"co.windyapp.android","versions":[]}]},{"name":"unlock-pro","description":"Unlocks pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":["SignatureVerificationPatch","LicenseValidationPatch"],"compatiblePackages":[{"name":"com.zombodroid.MemeGenerator","versions":["4.6364","4.6370","4.6375","4.6377"]}]},{"name":"unlock-pro","description":"Unlocks premium features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.candylink.openvpn","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all professional features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"org.totschnig.myexpenses","versions":["3.4.9"]}]},{"name":"unlock-pro","description":"Unlocks pro features.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.vsco.cam","versions":[]}]},{"name":"unlock-themes","description":"Unlocks all themes that are inaccessible until a certain level is reached.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ticktick.task","versions":[]}]},{"name":"unlock-trial","description":"Unlocks the trial version.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"net.dinglisch.android.taskerm","versions":[]}]},{"name":"upgrade-button-remover","description":"Removes the upgrade tab from the pivot bar.","version":"0.0.1","excluded":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":[]}]},{"name":"vanced-microg-support","description":"Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG.","version":"0.0.1","excluded":false,"options":[],"dependencies":["microg-resource-patch","hide-cast-button","client-spoof"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"video-ads","description":"Removes ads in the video player.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"video-speed","description":"Adds custom video speeds and ability to remember the playback speed you chose in the video playback speed flyout.","version":"0.0.1","excluded":false,"options":[],"dependencies":["custom-video-speed","remember-playback-speed"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]},{"name":"wide-searchbar","description":"Replaces the search icon with a wide search bar. This will hide the YouTube logo when active.","version":"0.0.1","excluded":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.16.37","18.19.35"]}]}]
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/extensions/Extensions.kt b/src/main/kotlin/app/revanced/extensions/Extensions.kt
index 7c70f90c6..37b9ffcee 100644
--- a/src/main/kotlin/app/revanced/extensions/Extensions.kt
+++ b/src/main/kotlin/app/revanced/extensions/Extensions.kt
@@ -1,11 +1,15 @@
package app.revanced.extensions
import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
+import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
+import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.Method
+import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
import org.jf.dexlib2.util.MethodUtil
import org.w3c.dom.Node
@@ -15,7 +19,7 @@ import org.w3c.dom.Node
*
* @return A [PatchResultError] for the [MethodFingerprint].
*/
-fun MethodFingerprint.toErrorResult() = PatchResultError("Failed to resolve $name")
+internal fun MethodFingerprint.toErrorResult() = PatchResultError("Failed to resolve $name")
/**
* Find the [MutableMethod] from a given [Method] in a [MutableClass].
@@ -23,7 +27,7 @@ fun MethodFingerprint.toErrorResult() = PatchResultError("Failed to resolve $nam
* @param method The [Method] to find.
* @return The [MutableMethod].
*/
-fun MutableClass.findMutableMethodOf(method: Method) = this.methods.first {
+internal fun MutableClass.findMutableMethodOf(method: Method) = this.methods.first {
MethodUtil.methodSignaturesMatch(it, method)
}
@@ -32,7 +36,7 @@ fun MutableClass.findMutableMethodOf(method: Method) = this.methods.first {
*
* @param transform the transformation function. original method goes in, transformed method goes out
*/
-fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod) {
+internal fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod) {
val transformedMethods = methods.map { it.transform() }
methods.clear()
methods.addAll(transformedMethods)
@@ -41,4 +45,29 @@ fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod)
internal fun Node.doRecursively(action: (Node) -> Unit) {
action(this)
for (i in 0 until this.childNodes.length) this.childNodes.item(i).doRecursively(action)
+}
+
+internal fun MutableMethod.injectHideViewCall(
+ insertIndex: Int,
+ viewRegister: Int,
+ classDescriptor: String,
+ targetMethod: String
+) = addInstruction(
+ insertIndex,
+ "invoke-static { v$viewRegister }, $classDescriptor->$targetMethod(Landroid/view/View;)V"
+)
+
+internal fun MutableMethod.findIndexForIdResource(resourceName: String): Int {
+ fun getIdResourceId(resourceName: String) = ResourceMappingPatch.resourceMappings.single {
+ it.type == "id" && it.name == resourceName
+ }.id
+
+ val resourceId = getIdResourceId(resourceName)
+ return implementation!!.instructions.indexOfFirst {
+ if (it.opcode != Opcode.CONST) return@indexOfFirst false
+
+ val literal = (it as WideLiteralInstruction).wideLiteral
+
+ return@indexOfFirst resourceId == literal
+ }
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/meta/ReadmeGenerator.kt b/src/main/kotlin/app/revanced/meta/ReadmeGenerator.kt
index 530ca0500..e8a951eac 100644
--- a/src/main/kotlin/app/revanced/meta/ReadmeGenerator.kt
+++ b/src/main/kotlin/app/revanced/meta/ReadmeGenerator.kt
@@ -5,6 +5,7 @@ import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
import app.revanced.patcher.extensions.PatchExtensions.description
import app.revanced.patcher.extensions.PatchExtensions.patchName
import app.revanced.patcher.patch.Patch
+import com.unascribed.flexver.FlexVerComparator
import java.io.File
internal class ReadmeGenerator : PatchesFileGenerator {
@@ -37,9 +38,8 @@ internal class ReadmeGenerator : PatchesFileGenerator {
}
}.let { commonMap ->
commonMap.maxByOrNull { it.value }?.value?.let {
- // This is not foolproof, because for example v1.0.0-dev.0 will be returned instead of v1.0.0-release.
- // Unfortunately this can not be solved easily because versioning can be complex.
- commonMap.entries.filter { mostCommon -> mostCommon.value == it }.maxBy { it.key }.key
+ commonMap.entries.filter { mostCommon -> mostCommon.value == it }
+ .maxOfWith(FlexVerComparator::compare, Map.Entry::key)
} ?: "all"
}
diff --git a/src/main/kotlin/app/revanced/patches/all/misc/packagename/patch/ChangePackageNamePatch.kt b/src/main/kotlin/app/revanced/patches/all/misc/packagename/patch/ChangePackageNamePatch.kt
index 20a754759..de1f10d06 100644
--- a/src/main/kotlin/app/revanced/patches/all/misc/packagename/patch/ChangePackageNamePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/all/misc/packagename/patch/ChangePackageNamePatch.kt
@@ -19,7 +19,7 @@ class ChangePackageNamePatch : ResourcePatch {
if (!packageName.matches(packageNameRegex))
return PatchResultError("Invalid package name")
- var originalPackageName = ""
+ var originalPackageName: String
context.xmlEditor["AndroidManifest.xml"].use { editor ->
val manifest = editor.file.getElementsByTagName("manifest").item(0) as Element
originalPackageName = manifest.getAttribute("package")
diff --git a/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/fingerprints/ProUnlockFingerprint.kt b/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/fingerprints/ProUnlockFingerprint.kt
index 7deff0a9c..2835fc0b2 100644
--- a/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/fingerprints/ProUnlockFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/fingerprints/ProUnlockFingerprint.kt
@@ -11,5 +11,8 @@ object ProUnlockFingerprint : MethodFingerprint(
Opcode.MOVE_RESULT,
Opcode.IF_EQZ
),
- customFingerprint = { it.definingClass == "Lcom/backdrops/wallpapers/data/local/DatabaseHandlerIAB;" && it.name == "lambda\$existPurchase\$0" }
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass == "Lcom/backdrops/wallpapers/data/local/DatabaseHandlerIAB;"
+ && methodDef.name == "lambda\$existPurchase\$0"
+ }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/patch/ProUnlockPatch.kt b/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/patch/ProUnlockPatch.kt
index 0365284d8..94f41526c 100644
--- a/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/patch/ProUnlockPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/backdrops/misc/pro/patch/ProUnlockPatch.kt
@@ -1,15 +1,14 @@
package app.revanced.patches.backdrops.misc.pro.patch
+import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
-import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.backdrops.misc.pro.annotations.ProUnlockCompatibility
@@ -25,17 +24,20 @@ class ProUnlockPatch : BytecodePatch(
listOf(ProUnlockFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
- val result = ProUnlockFingerprint.result ?: return PatchResultError("${ProUnlockFingerprint.name} not found")
+ ProUnlockFingerprint.result?.let { result ->
+ val registerIndex = result.scanResult.patternScanResult!!.endIndex - 1
- val moveRegisterInstruction = result.mutableMethod.instruction(result.scanResult.patternScanResult!!.endIndex - 1)
- val register = (moveRegisterInstruction as OneRegisterInstruction).registerA
+ result.mutableMethod.apply {
+ val register = instruction(registerIndex).registerA
+ addInstructions(
+ result.scanResult.patternScanResult!!.endIndex,
+ """
+ const/4 v$register, 0x1
+ """
+ )
+ }
- result.mutableMethod.addInstructions(
- result.scanResult.patternScanResult!!.endIndex,
- """
- const/4 v$register, 0x1
- """
- )
+ } ?: return ProUnlockFingerprint.toErrorResult()
return PatchResultSuccess()
}
diff --git a/src/main/kotlin/app/revanced/patches/candylinkvpn/annotations/UnlockProCompatibility.kt b/src/main/kotlin/app/revanced/patches/candylinkvpn/annotations/UnlockProCompatibility.kt
new file mode 100644
index 000000000..36c0f653c
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/candylinkvpn/annotations/UnlockProCompatibility.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.candylinkvpn.annotations
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("com.candylink.openvpn")])
+@Target(AnnotationTarget.CLASS)
+internal annotation class UnlockProCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/candylinkvpn/fingereprints/IsPremiumPurchasedFingerprint.kt b/src/main/kotlin/app/revanced/patches/candylinkvpn/fingereprints/IsPremiumPurchasedFingerprint.kt
new file mode 100644
index 000000000..394b3c1f4
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/candylinkvpn/fingereprints/IsPremiumPurchasedFingerprint.kt
@@ -0,0 +1,11 @@
+package app.revanced.patches.candylinkvpn.fingereprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+
+object IsPremiumPurchasedFingerprint : MethodFingerprint(
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass.endsWith("PreferenceProvider;") &&
+ methodDef.name == "isPremiumPurchased"
+ }
+) {
+}
diff --git a/src/main/kotlin/app/revanced/patches/candylinkvpn/patch/UnlockProPatch.kt b/src/main/kotlin/app/revanced/patches/candylinkvpn/patch/UnlockProPatch.kt
new file mode 100644
index 000000000..9905df4de
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/candylinkvpn/patch/UnlockProPatch.kt
@@ -0,0 +1,37 @@
+package app.revanced.patches.candylinkvpn.patch
+
+import app.revanced.extensions.toErrorResult
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patches.candylinkvpn.annotations.UnlockProCompatibility
+import app.revanced.patches.candylinkvpn.fingereprints.IsPremiumPurchasedFingerprint
+
+@Patch
+@Name("unlock-pro")
+@Description("Unlocks premium features.")
+@UnlockProCompatibility
+@Version("0.0.1")
+class UnlockProPatch : BytecodePatch(
+ listOf(IsPremiumPurchasedFingerprint)
+) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ IsPremiumPurchasedFingerprint.result?.let {
+ it.mutableMethod.addInstructions(
+ 0,
+ """
+ const/4 v0, 0x1
+ return v0
+ """
+ )
+ } ?: return IsPremiumPurchasedFingerprint.toErrorResult()
+
+ return PatchResultSuccess()
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/citra/misc/premium/fingerprints/PremiumUnlockFingerprint.kt b/src/main/kotlin/app/revanced/patches/citra/misc/premium/fingerprints/PremiumUnlockFingerprint.kt
index 347c31a2d..736664734 100644
--- a/src/main/kotlin/app/revanced/patches/citra/misc/premium/fingerprints/PremiumUnlockFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/citra/misc/premium/fingerprints/PremiumUnlockFingerprint.kt
@@ -3,5 +3,7 @@ package app.revanced.patches.citra.misc.premium.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object PremiumUnlockFingerprint : MethodFingerprint(
- customFingerprint = { it.definingClass == "Lorg/citra/citra_emu/ui/main/MainActivity;" && it.name == "isPremiumActive" }
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass == "Lorg/citra/citra_emu/ui/main/MainActivity;" && methodDef.name == "isPremiumActive"
+ }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/finanzonline/detection/bootloader/fingerprints/BootStateFingerprint.kt b/src/main/kotlin/app/revanced/patches/finanzonline/detection/bootloader/fingerprints/BootStateFingerprint.kt
index 766147aca..f6aff1191 100644
--- a/src/main/kotlin/app/revanced/patches/finanzonline/detection/bootloader/fingerprints/BootStateFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/finanzonline/detection/bootloader/fingerprints/BootStateFingerprint.kt
@@ -5,9 +5,9 @@ import org.jf.dexlib2.AccessFlags
object BootStateFingerprint : MethodFingerprint(
"Z",
- access = AccessFlags.PUBLIC.value,
+ accessFlags = AccessFlags.PUBLIC.value,
strings = listOf("Boot state of device: %s"),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/AttestationHelper;")
}
)
diff --git a/src/main/kotlin/app/revanced/patches/finanzonline/detection/bootloader/fingerprints/BootloaderDetectionFingerprint.kt b/src/main/kotlin/app/revanced/patches/finanzonline/detection/bootloader/fingerprints/BootloaderDetectionFingerprint.kt
index 2d24a6ccc..9bfe0ba21 100644
--- a/src/main/kotlin/app/revanced/patches/finanzonline/detection/bootloader/fingerprints/BootloaderDetectionFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/finanzonline/detection/bootloader/fingerprints/BootloaderDetectionFingerprint.kt
@@ -5,9 +5,9 @@ import org.jf.dexlib2.AccessFlags
object BootloaderDetectionFingerprint : MethodFingerprint(
"Z",
- access = AccessFlags.PUBLIC.value,
+ accessFlags = AccessFlags.PUBLIC.value,
strings = listOf("Creation of attestation key succeeded", "Creation of attestation key failed"),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/AttestationHelper;")
}
)
diff --git a/src/main/kotlin/app/revanced/patches/finanzonline/detection/root/fingerprints/RootDetectionFingerprint.kt b/src/main/kotlin/app/revanced/patches/finanzonline/detection/root/fingerprints/RootDetectionFingerprint.kt
index b2e793da4..3c3617dcd 100644
--- a/src/main/kotlin/app/revanced/patches/finanzonline/detection/root/fingerprints/RootDetectionFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/finanzonline/detection/root/fingerprints/RootDetectionFingerprint.kt
@@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object RootDetectionFingerprint : MethodFingerprint(
"L",
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lat/gv/bmf/bmf2go/tools/utils/z;"
}
)
diff --git a/src/main/kotlin/app/revanced/patches/hexeditor/ad/fingerprints/PrimaryAdsFingerprint.kt b/src/main/kotlin/app/revanced/patches/hexeditor/ad/fingerprints/PrimaryAdsFingerprint.kt
index 34c3e94af..ada038515 100644
--- a/src/main/kotlin/app/revanced/patches/hexeditor/ad/fingerprints/PrimaryAdsFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/hexeditor/ad/fingerprints/PrimaryAdsFingerprint.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.hexeditor.ad.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object PrimaryAdsFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("PreferencesHelper;") && methodDef.name == "isAdsDisabled"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/fingerprints/CheckProFingerprint.kt b/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/fingerprints/CheckProFingerprint.kt
index 945ef2ca9..8ecdb5032 100644
--- a/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/fingerprints/CheckProFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/fingerprints/CheckProFingerprint.kt
@@ -4,5 +4,5 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object CheckProFingerprint : MethodFingerprint(
"Z",
- customFingerprint = { it.definingClass.endsWith("IPSPurchaseRepository;")}
+ customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("IPSPurchaseRepository;")}
)
diff --git a/src/main/kotlin/app/revanced/patches/idaustria/detection/root/fingerprints/RootDetectionFingerprint.kt b/src/main/kotlin/app/revanced/patches/idaustria/detection/root/fingerprints/RootDetectionFingerprint.kt
index a64808a5f..185a9e5ad 100644
--- a/src/main/kotlin/app/revanced/patches/idaustria/detection/root/fingerprints/RootDetectionFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/idaustria/detection/root/fingerprints/RootDetectionFingerprint.kt
@@ -5,8 +5,8 @@ import org.jf.dexlib2.AccessFlags
object RootDetectionFingerprint : MethodFingerprint(
"V",
- access = AccessFlags.PUBLIC.value,
- customFingerprint = { methodDef ->
+ accessFlags = AccessFlags.PUBLIC.value,
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/DeviceIntegrityCheck;")
}
)
diff --git a/src/main/kotlin/app/revanced/patches/idaustria/detection/signature/fingerprints/SpoofSignatureFingerprint.kt b/src/main/kotlin/app/revanced/patches/idaustria/detection/signature/fingerprints/SpoofSignatureFingerprint.kt
index 34aa826a3..c11b2e0b6 100644
--- a/src/main/kotlin/app/revanced/patches/idaustria/detection/signature/fingerprints/SpoofSignatureFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/idaustria/detection/signature/fingerprints/SpoofSignatureFingerprint.kt
@@ -6,8 +6,8 @@ import org.jf.dexlib2.AccessFlags
object SpoofSignatureFingerprint : MethodFingerprint(
"L",
parameters = listOf("L"),
- access = AccessFlags.PRIVATE.value,
- customFingerprint = { methodDef ->
+ accessFlags = AccessFlags.PRIVATE.value,
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/SL2Step1Task;") && methodDef.name == "getPubKey"
}
)
diff --git a/src/main/kotlin/app/revanced/patches/inshorts/ad/fingerprints/InshortsAdsFingerprint.kt b/src/main/kotlin/app/revanced/patches/inshorts/ad/fingerprints/InshortsAdsFingerprint.kt
index 1cbb57933..0aba22b1b 100644
--- a/src/main/kotlin/app/revanced/patches/inshorts/ad/fingerprints/InshortsAdsFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/inshorts/ad/fingerprints/InshortsAdsFingerprint.kt
@@ -1,9 +1,8 @@
package app.revanced.patches.inshorts.ad.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import org.jf.dexlib2.Opcode
object InshortsAdsFingerprint : MethodFingerprint(
"V",
- strings = listOf("GoogleAdLoader","exception in requestAd")
+ strings = listOf("GoogleAdLoader","exception in requestAd"),
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/MediaAdFingerprint.kt b/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/MediaAdFingerprint.kt
index d505347af..b31290f70 100644
--- a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/MediaAdFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/MediaAdFingerprint.kt
@@ -4,17 +4,18 @@ import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
+import org.jf.dexlib2.iface.ClassDef
import org.jf.dexlib2.iface.Method
abstract class MediaAdFingerprint(
returnType: String? = "Z",
- access: Int? = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ accessFlags: Int? = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters: Iterable? = listOf(),
opcodes: Iterable?,
- customFingerprint: ((methodDef: Method) -> Boolean)? = null
+ customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null
) : MethodFingerprint(
returnType,
- access,
+ accessFlags,
parameters,
opcodes,
customFingerprint = customFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/PaidPartnershipAdFingerprint.kt b/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/PaidPartnershipAdFingerprint.kt
index 0dfa62a77..0f10168c6 100644
--- a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/PaidPartnershipAdFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/PaidPartnershipAdFingerprint.kt
@@ -14,7 +14,7 @@ object PaidPartnershipAdFingerprint : MediaAdFingerprint(
Opcode.IPUT_BOOLEAN,
Opcode.IPUT_BOOLEAN
),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("ClipsEditMetadataController;")
}
) {
diff --git a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/patch/HideTimelineAdsPatch.kt b/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/patch/HideTimelineAdsPatch.kt
index 5eb220cfc..6ba2dd958 100644
--- a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/patch/HideTimelineAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/patch/HideTimelineAdsPatch.kt
@@ -55,8 +55,8 @@ class HideTimelineAdsPatch : BytecodePatch(
val scanStart = scanResult.patternScanResult!!.startIndex
val jumpIndex = scanStart - 1
- val mediaInstanceRegister = (mutableMethod.instruction(scanStart) as FiveRegisterInstruction).registerC
- val freeRegister = (mutableMethod.instruction(jumpIndex) as OneRegisterInstruction).registerA
+ val mediaInstanceRegister = mutableMethod.instruction(scanStart).registerC
+ val freeRegister = mutableMethod.instruction(jumpIndex).registerA
val returnFalseLabel = "an_ad"
diff --git a/src/main/kotlin/app/revanced/patches/memegenerator/detection/license/fingerprint/LicenseValidationFingerprint.kt b/src/main/kotlin/app/revanced/patches/memegenerator/detection/license/fingerprint/LicenseValidationFingerprint.kt
index 205bca30a..9de66ac2a 100644
--- a/src/main/kotlin/app/revanced/patches/memegenerator/detection/license/fingerprint/LicenseValidationFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/memegenerator/detection/license/fingerprint/LicenseValidationFingerprint.kt
@@ -7,7 +7,7 @@ import org.jf.dexlib2.Opcode
object LicenseValidationFingerprint : MethodFingerprint(
returnType = "Z",
- access = AccessFlags.PUBLIC or AccessFlags.STATIC,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("Landroid/content/Context;"),
opcodes = listOf(
Opcode.INVOKE_STATIC,
diff --git a/src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/fingerprint/VerifySignatureFingerprint.kt b/src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/fingerprint/VerifySignatureFingerprint.kt
index 7c0304ebb..bc8cdc9fb 100644
--- a/src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/fingerprint/VerifySignatureFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/memegenerator/detection/signature/fingerprint/VerifySignatureFingerprint.kt
@@ -9,7 +9,7 @@ import org.jf.dexlib2.Opcode
@FuzzyPatternScanMethod(2)
object VerifySignatureFingerprint : MethodFingerprint(
returnType = "Z",
- access = AccessFlags.PUBLIC or AccessFlags.STATIC,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("Landroid/app/Activity;"),
opcodes = listOf(
Opcode.SGET_OBJECT,
diff --git a/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/annotations/UnlockProCompatibility.kt b/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/annotations/UnlockProCompatibility.kt
index bf92bccaa..b93215674 100644
--- a/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/annotations/UnlockProCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/annotations/UnlockProCompatibility.kt
@@ -3,6 +3,15 @@ package app.revanced.patches.memegenerator.misc.pro.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility([Package("com.zombodroid.MemeGenerator", arrayOf("4.6364"))])
+@Compatibility(
+ [Package(
+ "com.zombodroid.MemeGenerator", arrayOf(
+ "4.6364",
+ "4.6370",
+ "4.6375",
+ "4.6377",
+ )
+ )]
+)
@Target(AnnotationTarget.CLASS)
internal annotation class UnlockProCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/fingerprint/IsFreeVersionFingerprint.kt b/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/fingerprint/IsFreeVersionFingerprint.kt
index be9b266ba..19f08da0e 100644
--- a/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/fingerprint/IsFreeVersionFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/memegenerator/misc/pro/fingerprint/IsFreeVersionFingerprint.kt
@@ -7,7 +7,7 @@ import org.jf.dexlib2.Opcode
object IsFreeVersionFingerprint : MethodFingerprint(
returnType = "Ljava/lang/Boolean;",
- access = AccessFlags.PUBLIC or AccessFlags.STATIC,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
strings = listOf("free"),
parameters = listOf("Landroid/content/Context;"),
opcodes = listOf(
diff --git a/src/main/kotlin/app/revanced/patches/messenger/ads/inbox/fingerprints/LoadInboxAdsFingerprint.kt b/src/main/kotlin/app/revanced/patches/messenger/ads/inbox/fingerprints/LoadInboxAdsFingerprint.kt
index c29b94448..3bb5c3a38 100644
--- a/src/main/kotlin/app/revanced/patches/messenger/ads/inbox/fingerprints/LoadInboxAdsFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/messenger/ads/inbox/fingerprints/LoadInboxAdsFingerprint.kt
@@ -10,9 +10,9 @@ object LoadInboxAdsFingerprint : MethodFingerprint(
"ads_load_begin",
"inbox_ads_fetch_start"
),
- access = AccessFlags.PUBLIC or AccessFlags.STATIC,
- customFingerprint = {
- it.definingClass == "Lcom/facebook/messaging/business/inboxads/plugins/inboxads/itemsupplier/InboxAdsItemSupplierImplementation;"
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass == "Lcom/facebook/messaging/business/inboxads/plugins/inboxads/itemsupplier/InboxAdsItemSupplierImplementation;"
}
)
diff --git a/src/main/kotlin/app/revanced/patches/messenger/inputfield/fingerprints/SendTypingIndicatorFingerprint.kt b/src/main/kotlin/app/revanced/patches/messenger/inputfield/fingerprints/SendTypingIndicatorFingerprint.kt
new file mode 100644
index 000000000..cff25ae29
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/messenger/inputfield/fingerprints/SendTypingIndicatorFingerprint.kt
@@ -0,0 +1,15 @@
+package app.revanced.patches.messenger.inputfield.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import org.jf.dexlib2.dexbacked.value.DexBackedStringEncodedValue
+
+object SendTypingIndicatorFingerprint : MethodFingerprint(
+ returnType = "V",
+ parameters = listOf(),
+ customFingerprint = { methodDef, classDef ->
+ methodDef.name == "run" && classDef.fields.any {
+ it.name == "__redex_internal_original_name"
+ && (it.initialValue as? DexBackedStringEncodedValue)?.value == "ConversationTypingContext\$sendActiveStateRunnable\$1"
+ }
+ }
+)
diff --git a/src/main/kotlin/app/revanced/patches/messenger/inputfield/fingerprints/SwitchMessangeInputEmojiButtonFingerprint.kt b/src/main/kotlin/app/revanced/patches/messenger/inputfield/fingerprints/SwitchMessangeInputEmojiButtonFingerprint.kt
new file mode 100644
index 000000000..ef01e1a5a
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/messenger/inputfield/fingerprints/SwitchMessangeInputEmojiButtonFingerprint.kt
@@ -0,0 +1,18 @@
+package app.revanced.patches.messenger.inputfield.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import org.jf.dexlib2.Opcode
+
+object SwitchMessangeInputEmojiButtonFingerprint : MethodFingerprint(
+ returnType = "V",
+ parameters = listOf("L", "Z"),
+ strings = listOf("afterTextChanged", "expression_search"),
+ opcodes = listOf(
+ Opcode.IGET_OBJECT,
+ Opcode.IF_EQZ,
+ Opcode.CONST_STRING,
+ Opcode.GOTO,
+ Opcode.CONST_STRING,
+ Opcode.GOTO
+ )
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/messenger/inputfield/patch/DisableSwitchingEmojiToStickerInMessageInputField.kt b/src/main/kotlin/app/revanced/patches/messenger/inputfield/patch/DisableSwitchingEmojiToStickerInMessageInputField.kt
new file mode 100644
index 000000000..3d577a339
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/messenger/inputfield/patch/DisableSwitchingEmojiToStickerInMessageInputField.kt
@@ -0,0 +1,37 @@
+package app.revanced.patches.messenger.inputfield.patch
+
+import app.revanced.extensions.toErrorResult
+import app.revanced.patcher.annotation.*
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.instruction
+import app.revanced.patcher.extensions.replaceInstruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patches.messenger.inputfield.fingerprints.SwitchMessangeInputEmojiButtonFingerprint
+import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
+
+@Patch
+@Name("disable-switching-emoji-to-sticker-in-message-input-field")
+@Description("Disables switching from emoji to sticker search mode in message input field")
+@Compatibility([Package("com.facebook.orca")])
+@Version("0.0.1")
+class DisableSwitchingEmojiToStickerInMessageInputField : BytecodePatch(listOf(SwitchMessangeInputEmojiButtonFingerprint)) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ SwitchMessangeInputEmojiButtonFingerprint.result?.let {
+ val setStringIndex = it.scanResult.patternScanResult!!.startIndex + 2
+
+ it.mutableMethod.apply {
+ val targetRegister = instruction(setStringIndex).registerA
+
+ replaceInstruction(
+ setStringIndex,
+ "const-string v$targetRegister, \"expression\""
+ )
+ }
+ } ?: throw SwitchMessangeInputEmojiButtonFingerprint.toErrorResult()
+
+ return PatchResultSuccess()
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/messenger/inputfield/patch/DisableTypingIndicator.kt b/src/main/kotlin/app/revanced/patches/messenger/inputfield/patch/DisableTypingIndicator.kt
new file mode 100644
index 000000000..d25d46ed9
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/messenger/inputfield/patch/DisableTypingIndicator.kt
@@ -0,0 +1,29 @@
+package app.revanced.patches.messenger.inputfield.patch
+
+import app.revanced.extensions.toErrorResult
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.annotation.Package
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.replaceInstruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patches.messenger.inputfield.fingerprints.SendTypingIndicatorFingerprint
+
+@Patch
+@Name("disable-typing-indicator")
+@Description("Disables the indicator while typing a message")
+@Compatibility([Package("com.facebook.orca")])
+@Version("0.0.1")
+class DisableTypingIndicator : BytecodePatch(listOf(SendTypingIndicatorFingerprint)) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ SendTypingIndicatorFingerprint.result?.mutableMethod?.replaceInstruction(0, "return-void")
+ ?: throw SendTypingIndicatorFingerprint.toErrorResult()
+
+ return PatchResultSuccess()
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/moneymanager/fingerprints/UnlockProFingerprint.kt b/src/main/kotlin/app/revanced/patches/moneymanager/fingerprints/UnlockProFingerprint.kt
index 9ea14f8ac..c7b6824a1 100644
--- a/src/main/kotlin/app/revanced/patches/moneymanager/fingerprints/UnlockProFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/moneymanager/fingerprints/UnlockProFingerprint.kt
@@ -13,7 +13,7 @@ object UnlockProFingerprint : MethodFingerprint(
Opcode.IGET_BOOLEAN,
Opcode.RETURN
),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("MainActivity;")
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/nyx/misc/pro/fingerprints/CheckProFingerprint.kt b/src/main/kotlin/app/revanced/patches/nyx/misc/pro/fingerprints/CheckProFingerprint.kt
index 90b0af58d..d03ed1527 100644
--- a/src/main/kotlin/app/revanced/patches/nyx/misc/pro/fingerprints/CheckProFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/nyx/misc/pro/fingerprints/CheckProFingerprint.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.nyx.misc.pro.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object CheckProFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("BillingManager;") && methodDef.name == "isProVersion"
}
)
diff --git a/src/main/kotlin/app/revanced/patches/photomath/detection/signature/fingerprints/CheckSignatureFingerprint.kt b/src/main/kotlin/app/revanced/patches/photomath/detection/signature/fingerprints/CheckSignatureFingerprint.kt
index 2f460c694..df2445be7 100644
--- a/src/main/kotlin/app/revanced/patches/photomath/detection/signature/fingerprints/CheckSignatureFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/photomath/detection/signature/fingerprints/CheckSignatureFingerprint.kt
@@ -7,11 +7,11 @@ import org.jf.dexlib2.Opcode
object CheckSignatureFingerprint : MethodFingerprint(
returnType = "V",
- access = AccessFlags.PUBLIC or AccessFlags.FINAL,
- customFingerprint = {
- (it.definingClass == "Lcom/microblink/photomath/main/activity/LauncherActivity;" ||
- it.definingClass == "Lcom/microblink/photomath/PhotoMath;") &&
- it.name == "onCreate"
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ customFingerprint = { methodDef, _ ->
+ (methodDef.definingClass == "Lcom/microblink/photomath/main/activity/LauncherActivity;" ||
+ methodDef.definingClass == "Lcom/microblink/photomath/PhotoMath;") &&
+ methodDef.name == "onCreate"
},
strings = listOf(
"currentSignature"
diff --git a/src/main/kotlin/app/revanced/patches/photomath/misc/unlockplus/annotations/UnlockPlusCompatibilty.kt b/src/main/kotlin/app/revanced/patches/photomath/misc/unlockplus/annotations/UnlockPlusCompatibilty.kt
index 29f8379df..aa73c1fd3 100644
--- a/src/main/kotlin/app/revanced/patches/photomath/misc/unlockplus/annotations/UnlockPlusCompatibilty.kt
+++ b/src/main/kotlin/app/revanced/patches/photomath/misc/unlockplus/annotations/UnlockPlusCompatibilty.kt
@@ -3,28 +3,6 @@ package app.revanced.patches.photomath.misc.unlockplus.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.microblink.photomath", arrayOf(
- "8.6.0",
- "8.7.0",
- "8.8.0",
- "8.9.0",
- "8.10.0",
- "8.11.0",
- "8.12.0",
- "8.13.0",
- "8.14.0",
- "8.15.0",
- "8.16.0",
- "8.17.0",
- "8.18.0",
- "8.18.1",
- "8.19.0",
- "8.20.0",
- "8.21.0",
- )
- )]
-)
+@Compatibility([Package("com.microblink.photomath", arrayOf("8.20.0"))])
@Target(AnnotationTarget.CLASS)
internal annotation class UnlockPlusCompatibilty
diff --git a/src/main/kotlin/app/revanced/patches/photomath/misc/unlockplus/fingerprints/IsPlusUnlockedFingerprint.kt b/src/main/kotlin/app/revanced/patches/photomath/misc/unlockplus/fingerprints/IsPlusUnlockedFingerprint.kt
index eb2f74644..9f9dddffa 100644
--- a/src/main/kotlin/app/revanced/patches/photomath/misc/unlockplus/fingerprints/IsPlusUnlockedFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/photomath/misc/unlockplus/fingerprints/IsPlusUnlockedFingerprint.kt
@@ -6,11 +6,11 @@ import org.jf.dexlib2.AccessFlags
object IsPlusUnlockedFingerprint : MethodFingerprint(
returnType = "Z",
- access = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
strings = listOf(
"genius"
),
customFingerprint = {
- methodDef -> methodDef.definingClass.endsWith("/User;")
+ methodDef, _ -> methodDef.definingClass.endsWith("/User;")
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/ad/banner/annotations/HideBannerCompatibility.kt b/src/main/kotlin/app/revanced/patches/reddit/ad/banner/annotations/HideBannerCompatibility.kt
index ffac6ed55..90daa6b62 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/ad/banner/annotations/HideBannerCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/ad/banner/annotations/HideBannerCompatibility.kt
@@ -5,18 +5,7 @@ import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
- "com.reddit.frontpage", arrayOf(
- "2023.05.0",
- "2023.06.0",
- "2023.07.0",
- "2023.07.1",
- "2023.08.0",
- "2023.09.0",
- "2023.09.1",
- "2023.10.0",
- "2023.11.0",
- "2023.12.0"
- )
+ "com.reddit.frontpage"
)]
)
@Target(AnnotationTarget.CLASS)
diff --git a/src/main/kotlin/app/revanced/patches/reddit/ad/general/annotations/GeneralAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/reddit/ad/general/annotations/GeneralAdsCompatibility.kt
deleted file mode 100644
index e513e941e..000000000
--- a/src/main/kotlin/app/revanced/patches/reddit/ad/general/annotations/GeneralAdsCompatibility.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package app.revanced.patches.reddit.ad.general.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [Package(
- "com.reddit.frontpage", arrayOf(
- "2021.45.0",
- "2022.43.0",
- "2023.05.0",
- "2023.06.0",
- "2023.07.0",
- "2023.07.1",
- "2023.08.0",
- "2023.09.0",
- "2023.09.1",
- "2023.10.0",
- "2023.11.0",
- "2023.12.0"
- )
- )]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class GeneralAdsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/reddit/ad/general/annotations/HideAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/reddit/ad/general/annotations/HideAdsCompatibility.kt
new file mode 100644
index 000000000..f8dbd2d66
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/reddit/ad/general/annotations/HideAdsCompatibility.kt
@@ -0,0 +1,12 @@
+package app.revanced.patches.reddit.ad.general.annotations
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility(
+ [Package(
+ "com.reddit.frontpage"
+ )]
+)
+@Target(AnnotationTarget.CLASS)
+internal annotation class HideAdsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/reddit/ad/general/patch/GeneralAdsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/ad/general/patch/HideAdsPatch.kt
similarity index 92%
rename from src/main/kotlin/app/revanced/patches/reddit/ad/general/patch/GeneralAdsPatch.kt
rename to src/main/kotlin/app/revanced/patches/reddit/ad/general/patch/HideAdsPatch.kt
index 86341a62a..7f58d558e 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/ad/general/patch/GeneralAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/ad/general/patch/HideAdsPatch.kt
@@ -8,7 +8,7 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.reddit.ad.general.annotations.GeneralAdsCompatibility
+import app.revanced.patches.reddit.ad.general.annotations.HideAdsCompatibility
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
@@ -16,11 +16,11 @@ import org.jf.dexlib2.iface.reference.StringReference
import org.jf.dexlib2.immutable.reference.ImmutableStringReference
@Patch
-@Name("general-reddit-ads")
+@Name("hide-ads")
@Description("Removes general ads from the Reddit frontpage and subreddits.")
-@GeneralAdsCompatibility
+@HideAdsCompatibility
@Version("0.0.1")
-class GeneralAdsPatch : BytecodePatch() {
+class HideAdsPatch : BytecodePatch() {
override fun execute(context: BytecodeContext): PatchResult {
context.classes.forEach { classDef ->
classDef.methods.forEach methodLoop@{ method ->
diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/fingerprints/PremiumIconFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/fingerprints/PremiumIconFingerprint.kt
index bb8bf0d35..c406791ed 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/fingerprints/PremiumIconFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/fingerprints/PremiumIconFingerprint.kt
@@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object PremiumIconFingerprint : MethodFingerprint(
"Z",
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("MyAccount;") && methodDef.name == "isPremiumSubscriber"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/annotations/SanitizeUrlQueryCompatibility.kt b/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/annotations/SanitizeUrlQueryCompatibility.kt
new file mode 100644
index 000000000..6ba4a8902
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/annotations/SanitizeUrlQueryCompatibility.kt
@@ -0,0 +1,12 @@
+package app.revanced.patches.reddit.misc.tracking.url.annotations
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility(
+ [Package(
+ "com.reddit.frontpage"
+ )]
+)
+@Target(AnnotationTarget.CLASS)
+internal annotation class SanitizeUrlQueryCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/fingerprints/ShareLinkFactoryFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/fingerprints/ShareLinkFactoryFingerprint.kt
new file mode 100644
index 000000000..e3ec8ff90
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/fingerprints/ShareLinkFactoryFingerprint.kt
@@ -0,0 +1,22 @@
+package app.revanced.patches.reddit.misc.tracking.url.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import org.jf.dexlib2.AccessFlags
+import org.jf.dexlib2.Opcode
+
+object ShareLinkFactoryFingerprint : MethodFingerprint(
+ returnType = "L",
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ opcodes = listOf(
+ Opcode.CONST_STRING,
+ Opcode.CONST_STRING,
+ Opcode.INVOKE_DIRECT,
+ Opcode.APUT_OBJECT,
+ Opcode.INVOKE_STATIC,
+ Opcode.MOVE_RESULT_OBJECT,
+ Opcode.INVOKE_STATIC, // Returns the URL.
+ Opcode.MOVE_RESULT_OBJECT
+ ),
+ customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("ShareLinkFactory;") }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/patch/SanitizeUrlQueryPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/patch/SanitizeUrlQueryPatch.kt
new file mode 100644
index 000000000..1f494a401
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/reddit/misc/tracking/url/patch/SanitizeUrlQueryPatch.kt
@@ -0,0 +1,52 @@
+package app.revanced.patches.reddit.misc.tracking.url.patch
+
+import app.revanced.extensions.toErrorResult
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.extensions.instruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.patch.annotations.RequiresIntegrations
+import app.revanced.patches.reddit.misc.tracking.url.annotations.SanitizeUrlQueryCompatibility
+import app.revanced.patches.reddit.misc.tracking.url.fingerprints.ShareLinkFactoryFingerprint
+import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
+
+@Patch
+@Name("sanitize-sharing-links")
+@Description("Removes (tracking) query parameters from the URLs when sharing links.")
+@SanitizeUrlQueryCompatibility
+@Version("0.0.1")
+@RequiresIntegrations
+class SanitizeUrlQueryPatch : BytecodePatch(
+ listOf(ShareLinkFactoryFingerprint)
+) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ ShareLinkFactoryFingerprint.result?.let { result ->
+ result.mutableMethod.apply {
+ val insertIndex = result.scanResult.patternScanResult!!.endIndex + 1
+ val urlRegister = instruction(insertIndex - 1).registerA
+
+ addInstructions(
+ insertIndex,
+ """
+ invoke-static {v$urlRegister}, $SANITIZE_METHOD_DESCRIPTOR
+ move-result-object v$urlRegister
+ """
+ )
+ }
+ } ?: return ShareLinkFactoryFingerprint.toErrorResult()
+
+ return PatchResultSuccess()
+ }
+
+ private companion object {
+ private const val SANITIZE_METHOD_DESCRIPTOR =
+ "Lapp/revanced/reddit/patches/SanitizeUrlQueryPatch;" +
+ "->stripQueryParameters(Ljava/lang/String;)Ljava/lang/String;"
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/shared/fingerprints/SeekbarOnDrawFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/fingerprints/SeekbarOnDrawFingerprint.kt
index 7afcdae85..8ec4e2567 100644
--- a/src/main/kotlin/app/revanced/patches/shared/fingerprints/SeekbarOnDrawFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/fingerprints/SeekbarOnDrawFingerprint.kt
@@ -4,5 +4,5 @@ package app.revanced.patches.shared.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object SeekbarOnDrawFingerprint : MethodFingerprint(
- customFingerprint = { it.name == "onDraw" }
+ customFingerprint = { methodDef, _ -> methodDef.name == "onDraw" }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/shared/fingerprints/WatchWhileActivityFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/fingerprints/WatchWhileActivityFingerprint.kt
index b10c5e23e..eefe790f0 100644
--- a/src/main/kotlin/app/revanced/patches/shared/fingerprints/WatchWhileActivityFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/fingerprints/WatchWhileActivityFingerprint.kt
@@ -4,7 +4,7 @@ package app.revanced.patches.shared.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object WatchWhileActivityFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("WatchWhileActivity;") && methodDef.name == ""
}
)
diff --git a/src/main/kotlin/app/revanced/patches/shared/integrations/patch/AbstractIntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/shared/integrations/patch/AbstractIntegrationsPatch.kt
index 2ef2e48dc..efa8d35be 100644
--- a/src/main/kotlin/app/revanced/patches/shared/integrations/patch/AbstractIntegrationsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/integrations/patch/AbstractIntegrationsPatch.kt
@@ -9,6 +9,9 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint.RegisterResolver
+import org.jf.dexlib2.Opcode
+import org.jf.dexlib2.iface.ClassDef
import org.jf.dexlib2.iface.Method
@Description("Applies mandatory patches to implement the ReVanced integrations into the application.")
@@ -24,10 +27,21 @@ abstract class AbstractIntegrationsPatch(
* @see MethodFingerprint
*/
abstract class IntegrationsFingerprint(
+ returnType: String? = null,
+ accessFlags: Int? = null,
+ parameters: Iterable? = null,
+ opcodes: Iterable? = null,
strings: Iterable? = null,
- customFingerprint: ((methodDef: Method) -> Boolean)? = null,
+ customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null,
private val contextRegisterResolver: (Method) -> Int = object : RegisterResolver {}
- ) : MethodFingerprint(strings = strings, customFingerprint = customFingerprint) {
+ ) : MethodFingerprint(
+ returnType,
+ accessFlags,
+ parameters,
+ opcodes,
+ strings,
+ customFingerprint
+ ) {
fun invoke(integrationsDescriptor: String): PatchResult {
result?.mutableMethod?.let { method ->
val contextRegister = contextRegisterResolver(method)
diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/fix/spoof/annotations/ClientSpoofCompatibility.kt b/src/main/kotlin/app/revanced/patches/shared/misc/fix/spoof/annotations/ClientSpoofCompatibility.kt
deleted file mode 100644
index dc3138144..000000000
--- a/src/main/kotlin/app/revanced/patches/shared/misc/fix/spoof/annotations/ClientSpoofCompatibility.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package app.revanced.patches.shared.misc.fix.spoof.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class ClientSpoofCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/fingerprints/CanScrollVerticallyFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/fingerprints/CanScrollVerticallyFingerprint.kt
index e5d137ca6..3301d2b34 100644
--- a/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/fingerprints/CanScrollVerticallyFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/fingerprints/CanScrollVerticallyFingerprint.kt
@@ -13,5 +13,5 @@ object CanScrollVerticallyFingerprint : MethodFingerprint(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
),
- customFingerprint = { methodDef -> methodDef.definingClass.endsWith("SwipeRefreshLayout;") }
+ customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("SwipeRefreshLayout;") }
)
diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/patch/VerticalScrollPatch.kt b/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/patch/VerticalScrollPatch.kt
index 557ccb5a3..e251f1dec 100644
--- a/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/patch/VerticalScrollPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/patch/VerticalScrollPatch.kt
@@ -13,26 +13,25 @@ import app.revanced.patches.shared.misc.fix.verticalscroll.annotations.VerticalS
import app.revanced.patches.shared.misc.fix.verticalscroll.fingerprints.CanScrollVerticallyFingerprint
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
-@Description("Fixes issues with scrolling on the home screen when the first component is of type EmptyComponent.")
+@Description("Fixes issues with refreshing the feed when the first component is of type EmptyComponent.")
@VerticalScrollCompatibility
@Version("0.0.1")
class VerticalScrollPatch : BytecodePatch(
listOf(CanScrollVerticallyFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
- val result = CanScrollVerticallyFingerprint.result ?: return CanScrollVerticallyFingerprint.toErrorResult()
+ CanScrollVerticallyFingerprint.result?.let {
+ it.mutableMethod.apply {
+ val moveResultIndex = it.scanResult.patternScanResult!!.endIndex
+ val moveResultRegister = instruction(moveResultIndex).registerA
- with(result) {
- val method = mutableMethod
-
- val moveResultIndex = scanResult.patternScanResult!!.endIndex
- val moveResultRegister = (method.instruction(moveResultIndex) as OneRegisterInstruction).registerA
-
- method.addInstruction(
- moveResultIndex + 1,
- "const/4 v$moveResultRegister, 0x0"
- )
- }
+ val insertIndex = moveResultIndex + 1
+ addInstruction(
+ insertIndex,
+ "const/4 v$moveResultRegister, 0x0"
+ )
+ }
+ } ?: return CanScrollVerticallyFingerprint.toErrorResult()
return PatchResultSuccess()
}
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/preference/BasePreference.kt b/src/main/kotlin/app/revanced/patches/shared/settings/preference/BasePreference.kt
index 1853a97c6..09fe4bc61 100644
--- a/src/main/kotlin/app/revanced/patches/shared/settings/preference/BasePreference.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/settings/preference/BasePreference.kt
@@ -9,23 +9,26 @@ import org.w3c.dom.Element
*
* @param key The key of the preference.
* @param title The title of the preference.
+ * @param tag The tag of the preference.
+ * @param summary The summary of the preference.
*/
internal abstract class BasePreference(
- override val key: String,
- override val title: StringResource,
-) : IPreference {
-
+ val key: String?,
+ val title: StringResource,
+ val summary: StringResource? = null,
+ val tag: String
+) {
/**
* Serialize preference element to XML.
* Overriding methods should invoke super and operate on its return value.
* @param ownerDocument Target document to create elements from.
* @param resourceCallback Called when a resource has been processed.
+ * @return The serialized element.
*/
- open fun serialize(ownerDocument: Document, resourceCallback: ((IResource) -> Unit)? = null): Element {
- return ownerDocument.createElement(tag).apply {
- if(key.isNotEmpty())
- setAttribute("android:key", key)
- setAttribute("android:title", "@string/${title.also { resourceCallback?.invoke(it) }.name}")
+ open fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit): Element =
+ ownerDocument.createElement(tag).apply {
+ if (key != null) setAttribute("android:key", key)
+ setAttribute("android:title", "@string/${title.also { resourceCallback.invoke(it) }.name}")
+ addSummary(summary?.also { resourceCallback.invoke(it) })
}
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/preference/BaseResource.kt b/src/main/kotlin/app/revanced/patches/shared/settings/preference/BaseResource.kt
index 5c5e4174b..61a9b35a2 100644
--- a/src/main/kotlin/app/revanced/patches/shared/settings/preference/BaseResource.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/settings/preference/BaseResource.kt
@@ -7,18 +7,19 @@ import org.w3c.dom.Element
* Base resource class for all resources.
*
* @param name The name of the resource.
+ * @param tag The tag of the resource.
*/
internal abstract class BaseResource(
- override val name: String
-) : IResource {
-
+ val name: String,
+ val tag: String
+) {
/**
* Serialize resource element to XML.
* Overriding methods should invoke super and operate on its return value.
* @param ownerDocument Target document to create elements from.
* @param resourceCallback Called when a resource has been processed.
*/
- open fun serialize(ownerDocument: Document, resourceCallback: ((IResource) -> Unit)? = null): Element {
+ open fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit = { }): Element {
return ownerDocument.createElement(tag).apply {
setAttribute("name", name)
}
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/preference/ComponentsExtensions.kt b/src/main/kotlin/app/revanced/patches/shared/settings/preference/ComponentsExtensions.kt
index b0e8ddbd6..21207188b 100644
--- a/src/main/kotlin/app/revanced/patches/shared/settings/preference/ComponentsExtensions.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/settings/preference/ComponentsExtensions.kt
@@ -10,7 +10,7 @@ import org.w3c.dom.Node
* @param resource The resource to add.
* @param resourceCallback Called when a resource has been processed.
*/
-internal fun Node.addResource(resource: BaseResource, resourceCallback: ((IResource) -> Unit)? = null) {
+internal fun Node.addResource(resource: BaseResource, resourceCallback: (BaseResource) -> Unit = { }) {
appendChild(resource.serialize(ownerDocument, resourceCallback))
}
@@ -20,7 +20,7 @@ internal fun Node.addResource(resource: BaseResource, resourceCallback: ((IResou
* @param preference The preference to add.
* @param resourceCallback Called when a resource has been processed.
*/
-internal fun Node.addPreference(preference: BasePreference, resourceCallback: ((IResource) -> Unit)? = null) {
+internal fun Node.addPreference(preference: BasePreference, resourceCallback: ((BaseResource) -> Unit) = { }) {
appendChild(preference.serialize(ownerDocument, resourceCallback))
}
@@ -30,10 +30,11 @@ internal fun Element.addSummary(summaryResource: StringResource?, summaryType: S
}
internal fun Element.addDefault(default: T) {
+ if (default is Boolean && !(default as Boolean)) return // No need to include the default, as no value already means 'false'
default?.let {
setAttribute(
"android:defaultValue", when (it) {
- is Boolean -> if (it) "true" else "false"
+ is Boolean -> it.toString()
is String -> it
else -> throw IllegalArgumentException("Unsupported default value type: ${it::class.java.name}")
}
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/preference/DefaultBasePreference.kt b/src/main/kotlin/app/revanced/patches/shared/settings/preference/DefaultBasePreference.kt
new file mode 100644
index 000000000..64d35878c
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/shared/settings/preference/DefaultBasePreference.kt
@@ -0,0 +1,32 @@
+package app.revanced.patches.shared.settings.preference
+
+import app.revanced.patches.shared.settings.preference.impl.StringResource
+import org.w3c.dom.Document
+
+/**
+ * Base preference class that also has a default value.
+ *
+ * @param key The key of the preference.
+ * @param title The title of the preference.
+ * @param tag The tag of the preference.
+ * @param summary The summary of the preference.
+ * @param default The default value of the preference.
+ */
+internal abstract class DefaultBasePreference(
+ key: String?,
+ title: StringResource,
+ summary: StringResource? = null,
+ tag: String,
+ val default: T? = null,
+) : BasePreference(key, title, summary, tag) {
+
+ /**
+ * Serialize preference element to XML.
+ * Overriding methods should invoke super and operate on its return value.
+ * @param ownerDocument Target document to create elements from.
+ * @param resourceCallback Called when a resource has been processed.
+ * @return The serialized element.
+ */
+ override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
+ super.serialize(ownerDocument, resourceCallback).apply { addDefault(default) }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/preference/IPreference.kt b/src/main/kotlin/app/revanced/patches/shared/settings/preference/IPreference.kt
deleted file mode 100644
index ec31835ba..000000000
--- a/src/main/kotlin/app/revanced/patches/shared/settings/preference/IPreference.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package app.revanced.patches.shared.settings.preference
-
-import app.revanced.patches.shared.settings.preference.impl.StringResource
-
-/**
- * Preference
- */
-internal interface IPreference {
- /**
- * Key of the preference.
- */
- val key: String
-
- /**
- * Title of the preference.
- */
- val title: StringResource
-
- /**
- * Tag name of the preference.
- */
- val tag: String
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/preference/IResource.kt b/src/main/kotlin/app/revanced/patches/shared/settings/preference/IResource.kt
deleted file mode 100644
index dc3fe610e..000000000
--- a/src/main/kotlin/app/revanced/patches/shared/settings/preference/IResource.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package app.revanced.patches.shared.settings.preference
-
-/**
- * Resource
- */
-internal interface IResource {
- /**
- * Name of the resource.
- */
- val name: String
-
- /**
- * Tag name of the resource.
- */
- val tag: String
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/ArrayResource.kt b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/ArrayResource.kt
index 90795e1f7..9db57cff0 100644
--- a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/ArrayResource.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/ArrayResource.kt
@@ -1,34 +1,29 @@
package app.revanced.patches.shared.settings.preference.impl
import app.revanced.patches.shared.settings.preference.BaseResource
-import app.revanced.patches.shared.settings.preference.IResource
import org.w3c.dom.Document
-import org.w3c.dom.Element
+// TODO: allow specifying an array resource file instead of using a list of StringResources
/**
- * Represents an array resource.
+ * An array resource.
*
* @param name The name of the array resource.
* @param items The items of the array resource.
*/
-// TODO: allow specifying an array resource file instead of using a list of StringResources
-internal data class ArrayResource(
- override val name: String,
+internal class ArrayResource(
+ name: String,
val items: List
-) : BaseResource(name) {
- override val tag = "string-array"
-
- override fun serialize(ownerDocument: Document, resourceCallback: ((IResource) -> Unit)?): Element {
- return super.serialize(ownerDocument, resourceCallback).apply {
+) : BaseResource(name, "string-array") {
+ override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
+ super.serialize(ownerDocument, resourceCallback).apply {
setAttribute("name", name)
items.forEach { item ->
- resourceCallback?.invoke(item)
+ resourceCallback.invoke(item)
this.appendChild(ownerDocument.createElement("item").also { itemNode ->
itemNode.textContent = "@string/${item.name}"
})
}
}
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/InputType.kt b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/InputType.kt
index 09432143b..7d3ec982d 100644
--- a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/InputType.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/InputType.kt
@@ -1,6 +1,8 @@
package app.revanced.patches.shared.settings.preference.impl
enum class InputType(val type: String) {
- STRING("text"),
+ TEXT("text"),
+ TEXT_CAP_CHARACTERS("textCapCharacters"),
+ TEXT_MULTI_LINE("textMultiLine"),
NUMBER("number"),
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/ListPreference.kt b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/ListPreference.kt
index 9f2f9f84e..3df3c87e9 100644
--- a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/ListPreference.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/ListPreference.kt
@@ -1,11 +1,9 @@
package app.revanced.patches.shared.settings.preference.impl
-import app.revanced.patches.shared.settings.preference.BasePreference
-import app.revanced.patches.shared.settings.preference.IResource
-import app.revanced.patches.shared.settings.preference.addDefault
+import app.revanced.patches.shared.settings.preference.BaseResource
+import app.revanced.patches.shared.settings.preference.DefaultBasePreference
import app.revanced.patches.shared.settings.preference.addSummary
import org.w3c.dom.Document
-import org.w3c.dom.Element
/**
* List preference.
@@ -14,25 +12,21 @@ import org.w3c.dom.Element
* @param title The title of the list preference.
* @param entries The human-readable entries of the list preference.
* @param entryValues The entry values of the list preference.
- * @param default The default entry value of the list preference.
* @param summary The summary of the list preference.
+ * @param default The default entry value of the list preference.
*/
internal class ListPreference(
key: String,
title: StringResource,
val entries: ArrayResource,
val entryValues: ArrayResource,
- val default: String? = null,
- val summary: StringResource? = null
-) : BasePreference(key, title) {
- override val tag: String = "ListPreference"
-
- override fun serialize(ownerDocument: Document, resourceCallback: ((IResource) -> Unit)?): Element {
- return super.serialize(ownerDocument, resourceCallback).apply {
- setAttribute("android:entries", "@array/${entries.also { resourceCallback?.invoke(it) }.name}")
- setAttribute("android:entryValues", "@array/${entryValues.also { resourceCallback?.invoke(it) }.name}")
- addDefault(default)
+ summary: StringResource? = null,
+ default: String? = null,
+) : DefaultBasePreference(key, title, summary, "ListPreference", default) {
+ override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
+ super.serialize(ownerDocument, resourceCallback).apply {
+ setAttribute("android:entries", "@array/${entries.also { resourceCallback.invoke(it) }.name}")
+ setAttribute("android:entryValues", "@array/${entryValues.also { resourceCallback.invoke(it) }.name}")
addSummary(summary)
}
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/NonInteractivePreference.kt b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/NonInteractivePreference.kt
index 9332bd17d..c97913c2a 100644
--- a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/NonInteractivePreference.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/NonInteractivePreference.kt
@@ -1,24 +1,27 @@
package app.revanced.patches.shared.settings.preference.impl
import app.revanced.patches.shared.settings.preference.BasePreference
-import app.revanced.patches.shared.settings.preference.IResource
+import app.revanced.patches.shared.settings.preference.BaseResource
import app.revanced.patches.shared.settings.preference.addSummary
import org.w3c.dom.Document
import org.w3c.dom.Element
/**
- * A simple static title and summary that is not backed by any preference key/value,
- * and cannot be changed by or interacted with by the user,
+ * A non interactive preference.
+ *
+ * Not backed by any preference key/value,
+ * and cannot be changed by or interacted with by the user.
+ *
+ * @param title The title of the preference.
+ * @param summary The summary of the text preference.
*/
internal class NonInteractivePreference(
title: StringResource,
- val summary: StringResource,
-) : BasePreference("", title) {
- override val tag: String = "Preference"
-
- override fun serialize(ownerDocument: Document, resourceCallback: ((IResource) -> Unit)?): Element {
+ summary: StringResource,
+) : BasePreference(null, title, summary, "Preference") {
+ override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit): Element {
return super.serialize(ownerDocument, resourceCallback).apply {
- addSummary(summary.also { resourceCallback?.invoke(it)
+ addSummary(summary?.also { resourceCallback.invoke(it)
setAttribute("android:selectable", false.toString())
})
}
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/Preference.kt b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/Preference.kt
index fcacd61d7..2ada5625d 100644
--- a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/Preference.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/Preference.kt
@@ -1,44 +1,41 @@
package app.revanced.patches.shared.settings.preference.impl
import app.revanced.patches.shared.settings.preference.BasePreference
-import app.revanced.patches.shared.settings.preference.IResource
-import app.revanced.patches.shared.settings.preference.addSummary
+import app.revanced.patches.shared.settings.preference.BaseResource
import org.w3c.dom.Document
-import org.w3c.dom.Element
/**
- * A Preference object.
+ * A preference object.
*
+ * @param key The key of the preference.
* @param title The title of the preference.
- * @param intent The intent of the preference.
* @param summary The summary of the text preference.
+ * @param intent The intent of the preference.
*/
internal class Preference(
key: String,
title: StringResource,
- val intent: Intent,
- val summary: StringResource? = null
-) : BasePreference(key, title) {
- override val tag: String = "Preference"
-
- /* Key-less constructor */
+ summary: StringResource,
+ val intent: Intent
+) : BasePreference(key, title, summary, "Preference") {
constructor(
title: StringResource,
- intent: Intent,
- summary: StringResource? = null
- ) : this("", title, intent, summary)
-
- override fun serialize(ownerDocument: Document, resourceCallback: ((IResource) -> Unit)?): Element {
- return super.serialize(ownerDocument, resourceCallback).apply {
- addSummary(summary?.also { resourceCallback?.invoke(it) })
+ summary: StringResource,
+ intent: Intent
+ ) : this("", title, summary, intent)
+ override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
+ super.serialize(ownerDocument, resourceCallback).apply {
this.appendChild(ownerDocument.createElement("intent").also { intentNode ->
intentNode.setAttribute("android:targetPackage", intent.targetPackage)
intentNode.setAttribute("android:data", intent.data)
intentNode.setAttribute("android:targetClass", intent.targetClass)
})
}
- }
- data class Intent(val targetPackage: String, val data: String, val targetClass: String)
+ internal class Intent(
+ internal val targetPackage: String,
+ internal val data: String,
+ internal val targetClass: String
+ )
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/PreferenceCategory.kt b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/PreferenceCategory.kt
index f575dfe3a..56e02f45d 100644
--- a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/PreferenceCategory.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/PreferenceCategory.kt
@@ -1,12 +1,11 @@
package app.revanced.patches.shared.settings.preference.impl
import app.revanced.patches.shared.settings.preference.BasePreference
-import app.revanced.patches.shared.settings.preference.IResource
+import app.revanced.patches.shared.settings.preference.BaseResource
import org.w3c.dom.Document
-import org.w3c.dom.Element
/**
- * Preference category.
+ * A preference category.
*
* @param key The key of the preference.
* @param title The title of the preference.
@@ -15,15 +14,13 @@ import org.w3c.dom.Element
internal open class PreferenceCategory(
key: String,
title: StringResource,
- var preferences: List
-) : BasePreference(key, title) {
- override val tag: String = "PreferenceCategory"
-
- override fun serialize(ownerDocument: Document, resourceCallback: ((IResource) -> Unit)?): Element {
- return super.serialize(ownerDocument, resourceCallback).apply {
+ var preferences: List,
+ tag: String = "PreferenceCategory"
+) : BasePreference(key, title, null, tag) {
+ override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
+ super.serialize(ownerDocument, resourceCallback).apply {
for (childPreference in preferences) {
this.appendChild(childPreference.serialize(ownerDocument, resourceCallback))
}
}
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/PreferenceScreen.kt b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/PreferenceScreen.kt
index b7c82ba6f..e6bf32d43 100644
--- a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/PreferenceScreen.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/PreferenceScreen.kt
@@ -1,13 +1,12 @@
package app.revanced.patches.shared.settings.preference.impl
import app.revanced.patches.shared.settings.preference.BasePreference
-import app.revanced.patches.shared.settings.preference.IResource
+import app.revanced.patches.shared.settings.preference.BaseResource
import app.revanced.patches.shared.settings.preference.addSummary
import org.w3c.dom.Document
-import org.w3c.dom.Element
/**
- * Preference screen.
+ * A preference screen.
*
* @param key The key of the preference.
* @param title The title of the preference.
@@ -18,17 +17,13 @@ internal open class PreferenceScreen(
key: String,
title: StringResource,
var preferences: List,
- val summary: StringResource? = null
-) : BasePreference(key, title) {
- override val tag: String = "PreferenceScreen"
+ summary: StringResource? = null
+) : BasePreference(key, title, summary, "PreferenceScreen") {
+ override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
+ super.serialize(ownerDocument, resourceCallback).apply {
+ addSummary(summary?.also { resourceCallback.invoke(it) })
- override fun serialize(ownerDocument: Document, resourceCallback: ((IResource) -> Unit)?): Element {
- return super.serialize(ownerDocument, resourceCallback).apply {
- addSummary(summary?.also { resourceCallback?.invoke(it) })
-
- for (childPreference in preferences) {
+ for (childPreference in preferences)
this.appendChild(childPreference.serialize(ownerDocument, resourceCallback))
- }
}
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/StringResource.kt b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/StringResource.kt
index 49471faa8..7934b1270 100644
--- a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/StringResource.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/StringResource.kt
@@ -1,31 +1,27 @@
package app.revanced.patches.shared.settings.preference.impl
import app.revanced.patches.shared.settings.preference.BaseResource
-import app.revanced.patches.shared.settings.preference.IResource
import org.w3c.dom.Document
-import org.w3c.dom.Element
/**
- * Represents a string value in the strings.xml file
+ * A string value.
+ * Represets a string in the strings.xml file.
*
- * @param name The name of the string
- * @param value The value of the string
- * @param formatted If the string is formatted. If false, the attribute will be set
+ * @param name The name of the string.
+ * @param value The value of the string.
+ * @param formatted If the string is formatted. If false, the attribute will be set.
*/
-internal data class StringResource(
- override val name: String,
+internal class StringResource(
+ name: String,
val value: String,
val formatted: Boolean = true
-) : BaseResource(name) {
- override val tag = "string"
+) : BaseResource(name, "string") {
- override fun serialize(ownerDocument: Document, resourceCallback: ((IResource) -> Unit)?): Element {
- return super.serialize(ownerDocument, resourceCallback).apply {
+ override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
+ super.serialize(ownerDocument, resourceCallback).apply {
// if the string is un-formatted, explicitly add the formatted attribute
- if (!formatted)
- setAttribute("formatted", "false")
+ if (!formatted) setAttribute("formatted", "false")
textContent = value
}
- }
}
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/SwitchPreference.kt b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/SwitchPreference.kt
index 2845849bc..5a9e6778e 100644
--- a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/SwitchPreference.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/SwitchPreference.kt
@@ -1,37 +1,36 @@
package app.revanced.patches.shared.settings.preference.impl
-import app.revanced.patches.shared.settings.preference.*
+import app.revanced.patches.shared.settings.preference.BaseResource
+import app.revanced.patches.shared.settings.preference.DefaultBasePreference
+import app.revanced.patches.shared.settings.preference.SummaryType
+import app.revanced.patches.shared.settings.preference.addSummary
import app.revanced.patches.shared.settings.resource.patch.AbstractSettingsResourcePatch.Companion.include
import org.w3c.dom.Document
import org.w3c.dom.Element
/**
- * Switch preference.
+ * A switch preference.
*
* @param key The key of the switch.
* @param title The title of the switch.
- * @param default The default value of the switch.
* @param summaryOn The summary to show when the preference is enabled.
* @param summaryOff The summary to show when the preference is disabled.
* @param userDialogMessage The message to show in a dialog when the user toggles the preference.
+ * @param default The default value of the switch.
*/
internal class SwitchPreference(
key: String, title: StringResource,
- val default: Boolean = false,
- val summaryOn: StringResource? = null,
- val summaryOff: StringResource? = null,
- val userDialogMessage: StringResource? = null
-) : BasePreference(key, title) {
- override val tag: String = "SwitchPreference"
-
- override fun serialize(ownerDocument: Document, resourceCallback: ((IResource) -> Unit)?): Element {
- // dialog message is stored as a regular string and later referenced by SettingsEnum
+ val summaryOn: StringResource,
+ val summaryOff: StringResource,
+ val userDialogMessage: StringResource? = null,
+ default: Boolean = false,
+) : DefaultBasePreference( key, title, null, "SwitchPreference", default) {
+ override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit): Element {
userDialogMessage?.include()
return super.serialize(ownerDocument, resourceCallback).apply {
- addDefault(default)
- addSummary(summaryOn?.also { resourceCallback?.invoke(it) }, SummaryType.ON)
- addSummary(summaryOff?.also { resourceCallback?.invoke(it) }, SummaryType.OFF)
+ addSummary(summaryOn.also { resourceCallback.invoke(it) }, SummaryType.ON)
+ addSummary(summaryOff.also { resourceCallback.invoke(it) }, SummaryType.OFF)
}
}
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/TextPreference.kt b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/TextPreference.kt
index 907a4a160..5895a5e6e 100644
--- a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/TextPreference.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/TextPreference.kt
@@ -1,35 +1,29 @@
package app.revanced.patches.shared.settings.preference.impl
-import app.revanced.patches.shared.settings.preference.BasePreference
-import app.revanced.patches.shared.settings.preference.IResource
-import app.revanced.patches.shared.settings.preference.addDefault
-import app.revanced.patches.shared.settings.preference.addSummary
+import app.revanced.patches.shared.settings.preference.BaseResource
+import app.revanced.patches.shared.settings.preference.DefaultBasePreference
import org.w3c.dom.Document
-import org.w3c.dom.Element
/**
- * Text preference.
+ * A text preference.
*
* @param key The key of the text preference.
* @param title The title of the text preference.
* @param inputType The input type of the text preference.
- * @param default The default value of the text preference.
* @param summary The summary of the text preference.
+ * @param default The default value of the text preference.
*/
internal class TextPreference(
- key: String,
+ key: String?,
title: StringResource,
- var inputType: InputType = InputType.STRING,
- val default: String? = null,
- val summary: StringResource? = null
-) : BasePreference(key, title) {
- override val tag: String = "EditTextPreference"
+ summary: StringResource?,
+ val inputType: InputType = InputType.TEXT,
+ default: String? = null,
+ tag: String = "app.revanced.integrations.settingsmenu.ResettableEditTextPreference"
+) : DefaultBasePreference(key, title, summary, tag, default) {
- override fun serialize(ownerDocument: Document, resourceCallback: ((IResource) -> Unit)?): Element {
- return super.serialize(ownerDocument, resourceCallback).apply {
+ override fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit) =
+ super.serialize(ownerDocument, resourceCallback).apply {
setAttribute("android:inputType", inputType.type)
- addDefault(default)
- addSummary(summary?.also { resourceCallback?.invoke(it) })
}
- }
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/resource/patch/AbstractSettingsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/shared/settings/resource/patch/AbstractSettingsResourcePatch.kt
index 778916b55..41ff37396 100644
--- a/src/main/kotlin/app/revanced/patches/shared/settings/resource/patch/AbstractSettingsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/shared/settings/resource/patch/AbstractSettingsResourcePatch.kt
@@ -6,7 +6,7 @@ import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patches.shared.settings.preference.BasePreference
-import app.revanced.patches.shared.settings.preference.IResource
+import app.revanced.patches.shared.settings.preference.BaseResource
import app.revanced.patches.shared.settings.preference.addPreference
import app.revanced.patches.shared.settings.preference.addResource
import app.revanced.patches.shared.settings.preference.impl.ArrayResource
@@ -108,7 +108,7 @@ abstract class AbstractSettingsResourcePatch(
*
* @throws IllegalArgumentException if the resource already exists.
*/
- internal fun IResource.include() {
+ internal fun BaseResource.include() {
when (this) {
is StringResource -> {
if (strings.any { it.name == name }) return
diff --git a/src/main/kotlin/app/revanced/patches/spotify/audio/bytecode/patch/DisableCaptureRestrictionBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/spotify/audio/bytecode/patch/DisableCaptureRestrictionBytecodePatch.kt
index 88aae6a28..cc656d112 100644
--- a/src/main/kotlin/app/revanced/patches/spotify/audio/bytecode/patch/DisableCaptureRestrictionBytecodePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/spotify/audio/bytecode/patch/DisableCaptureRestrictionBytecodePatch.kt
@@ -8,18 +8,13 @@ import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
-import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.spotify.audio.annotation.DisableCaptureRestrictionCompatibility
import app.revanced.patches.spotify.audio.fingerprints.DisableCaptureRestrictionAudioDriverFingerprint
import app.revanced.patches.spotify.audio.resource.patch.DisableCaptureRestrictionResourcePatch
-import org.jf.dexlib2.Opcode
-import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
-import org.jf.dexlib2.iface.instruction.ReferenceInstruction
-import org.jf.dexlib2.iface.reference.MethodReference
@Patch
@Name("disable-capture-restriction")
@@ -35,49 +30,16 @@ class DisableCaptureRestrictionBytecodePatch : BytecodePatch(
override fun execute(context: BytecodeContext): PatchResult {
val method = DisableCaptureRestrictionAudioDriverFingerprint.result!!.mutableMethod
- var invokePosition: Int? = null
- var invokeParamRegister: Int? = null
-
- // Find INVOKE_VIRTUAL opcode with call to AudioAttributesBuilder.setAllowedCapturePolicy(I)
- for ((index, instruction) in method.implementation!!.instructions.withIndex()) {
- if(instruction.opcode != Opcode.INVOKE_VIRTUAL)
- continue
-
- val methodName = ((instruction as ReferenceInstruction).reference as MethodReference).name
- if (methodName != "setAllowedCapturePolicy")
- continue
-
- // Store register of the integer parameter for setAllowedCapturePolicy
- invokeParamRegister = (instruction as FiveRegisterInstruction).registerD
- invokePosition = index
- }
-
- if(invokePosition == null || invokeParamRegister == null)
- return PatchResultError("Cannot find setAllowedCapturePolicy method call")
-
- // Walk back to the const/4 instruction that sets the parameter register
- var matchFound = false
- for (index in invokePosition downTo 0) {
- val instruction = method.instruction(index)
- if(instruction.opcode != Opcode.CONST_4)
- continue
-
- val register = (instruction as OneRegisterInstruction).registerA
- if(register != invokeParamRegister)
- continue
-
- // Replace parameter value
- method.replaceInstruction(
- index, "const/4 v$register, $ALLOW_CAPTURE_BY_ALL"
+ method.apply {
+ // Replace constant
+ val original = instruction(0) as OneRegisterInstruction
+ replaceInstruction(
+ 0,
+ "const/4 v${original.registerA}, $ALLOW_CAPTURE_BY_ALL"
)
- matchFound = true
- break
}
- return if (matchFound)
- PatchResultSuccess()
- else
- PatchResultError("Const instruction not found")
+ return PatchResultSuccess()
}
private companion object {
diff --git a/src/main/kotlin/app/revanced/patches/spotify/audio/fingerprints/DisableCaptureRestrictionAudioDriverFingerprint.kt b/src/main/kotlin/app/revanced/patches/spotify/audio/fingerprints/DisableCaptureRestrictionAudioDriverFingerprint.kt
index 191755518..97b9193e6 100644
--- a/src/main/kotlin/app/revanced/patches/spotify/audio/fingerprints/DisableCaptureRestrictionAudioDriverFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/spotify/audio/fingerprints/DisableCaptureRestrictionAudioDriverFingerprint.kt
@@ -1,10 +1,27 @@
package app.revanced.patches.spotify.audio.fingerprints
+import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import org.jf.dexlib2.AccessFlags
+import org.jf.dexlib2.Opcode
+import org.jf.dexlib2.iface.instruction.ReferenceInstruction
+import org.jf.dexlib2.iface.reference.MethodReference
object DisableCaptureRestrictionAudioDriverFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
- methodDef.definingClass == "Lcom/spotify/playback/playbacknative/AudioDriver;" && methodDef.name == "constructAudioAttributes"
+ "L",
+ AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.SYNTHETIC or AccessFlags.BRIDGE,
+ listOf("L"),
+ listOf(
+ Opcode.CONST_4,
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.MOVE_RESULT_OBJECT,
+ Opcode.RETURN_OBJECT
+ ),
+ customFingerprint = { methodDef, _ ->
+ // Check for method call to AudioAttributes$Builder.setAllowedCapturePolicy Android API
+ methodDef.implementation?.instructions?.any {
+ ((it as? ReferenceInstruction)?.reference as? MethodReference)?.name == "setAllowedCapturePolicy"
+ } == true
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/ads/annotations/DisableAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/syncforreddit/ads/annotations/DisableAdsCompatibility.kt
new file mode 100644
index 000000000..c6cf42886
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/syncforreddit/ads/annotations/DisableAdsCompatibility.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.syncforreddit.ads.annotations
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("com.laurencedawson.reddit_sync")])
+@Target(AnnotationTarget.CLASS)
+internal annotation class DisableAdsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/ads/fingerprints/IsAdsEnabledFingerprint.kt b/src/main/kotlin/app/revanced/patches/syncforreddit/ads/fingerprints/IsAdsEnabledFingerprint.kt
new file mode 100644
index 000000000..ff01b38cf
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/syncforreddit/ads/fingerprints/IsAdsEnabledFingerprint.kt
@@ -0,0 +1,11 @@
+package app.revanced.patches.syncforreddit.ads.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import org.jf.dexlib2.AccessFlags
+
+object IsAdsEnabledFingerprint : MethodFingerprint(
+ returnType = "Z",
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
+ strings = listOf("SyncIapHelper")
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/ads/patch/DisableAdsPatch.kt b/src/main/kotlin/app/revanced/patches/syncforreddit/ads/patch/DisableAdsPatch.kt
new file mode 100644
index 000000000..ef5e2a945
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/syncforreddit/ads/patch/DisableAdsPatch.kt
@@ -0,0 +1,39 @@
+package app.revanced.patches.syncforreddit.ads.patch
+
+import app.revanced.extensions.toErrorResult
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patches.syncforreddit.ads.annotations.DisableAdsCompatibility
+import app.revanced.patches.syncforreddit.ads.fingerprints.IsAdsEnabledFingerprint
+import app.revanced.patches.syncforreddit.detection.piracy.patch.DisablePiracyDetectionPatch
+
+@Patch
+@Name("disable-ads")
+@DependsOn([DisablePiracyDetectionPatch::class])
+@Description("Disables ads.")
+@Version("0.0.1")
+@DisableAdsCompatibility
+class DisableAdsPatch : BytecodePatch(listOf(IsAdsEnabledFingerprint)) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ IsAdsEnabledFingerprint.result?.mutableMethod?.apply {
+ addInstructions(
+ 0,
+ """
+ const/4 v0, 0x0
+ return v0
+ """
+ )
+ } ?: return IsAdsEnabledFingerprint.toErrorResult()
+
+ return PatchResultSuccess()
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/detection/piracy/fingerprints/PiracyDetectionFingerprint.kt b/src/main/kotlin/app/revanced/patches/syncforreddit/detection/piracy/fingerprints/PiracyDetectionFingerprint.kt
new file mode 100644
index 000000000..d3c87f360
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/syncforreddit/detection/piracy/fingerprints/PiracyDetectionFingerprint.kt
@@ -0,0 +1,29 @@
+package app.revanced.patches.syncforreddit.detection.piracy.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import org.jf.dexlib2.AccessFlags
+import org.jf.dexlib2.Opcode
+import org.jf.dexlib2.iface.instruction.ReferenceInstruction
+import org.jf.dexlib2.iface.reference.TypeReference
+
+object PiracyDetectionFingerprint : MethodFingerprint(
+ returnType = "V",
+ accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
+ opcodes = listOf(
+ Opcode.NEW_INSTANCE,
+ Opcode.INVOKE_DIRECT,
+ Opcode.NEW_INSTANCE,
+ Opcode.INVOKE_DIRECT,
+ Opcode.INVOKE_VIRTUAL
+ ),
+ customFingerprint = { method, _ ->
+ method.implementation?.instructions?.any {
+ if (it.opcode != Opcode.NEW_INSTANCE) return@any false
+
+ val reference = (it as ReferenceInstruction).reference
+
+ reference.toString() == "Lcom/github/javiersantos/piracychecker/PiracyChecker;"
+ } ?: false
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/syncforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt b/src/main/kotlin/app/revanced/patches/syncforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt
new file mode 100644
index 000000000..ad7f2f9a1
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/syncforreddit/detection/piracy/patch/DisablePiracyDetectionPatch.kt
@@ -0,0 +1,28 @@
+package app.revanced.patches.syncforreddit.detection.piracy.patch
+
+import app.revanced.extensions.toErrorResult
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patches.syncforreddit.detection.piracy.fingerprints.PiracyDetectionFingerprint
+
+@Description("Disables detection of modified versions.")
+@Version("0.0.1")
+class DisablePiracyDetectionPatch : BytecodePatch(listOf(PiracyDetectionFingerprint)) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ PiracyDetectionFingerprint.result?.mutableMethod?.apply {
+ addInstructions(
+ 0,
+ """
+ return-void
+ """
+ )
+ } ?: return PiracyDetectionFingerprint.toErrorResult()
+
+ return PatchResultSuccess()
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/fingerprints/CheckLockedThemesFingerprint.kt b/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/fingerprints/CheckLockedThemesFingerprint.kt
index dccab403f..0f019f078 100644
--- a/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/fingerprints/CheckLockedThemesFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/fingerprints/CheckLockedThemesFingerprint.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.ticktick.misc.themeunlock.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object CheckLockedThemesFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("Theme;") && methodDef.name == "isLockedTheme"
}
)
diff --git a/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/fingerprints/SetThemeFingerprint.kt b/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/fingerprints/SetThemeFingerprint.kt
index dc22b02c5..f5e8430d0 100644
--- a/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/fingerprints/SetThemeFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/fingerprints/SetThemeFingerprint.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.ticktick.misc.themeunlock.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object SetThemeFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("ThemePreviewActivity;") && methodDef.name == "lambda\$updateUserBtn\$1"
}
)
diff --git a/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/patch/UnlockThemePatch.kt b/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/patch/UnlockThemePatch.kt
index 8cc8fdd9c..d61f3539c 100644
--- a/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/patch/UnlockThemePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/patch/UnlockThemePatch.kt
@@ -36,7 +36,7 @@ class UnlockProPatch : BytecodePatch(
)
val setThemeMethod = SetThemeFingerprint.result!!.mutableMethod
- setThemeMethod.removeInstructions(0, 9)
+ setThemeMethod.removeInstructions(0, 10)
return PatchResultSuccess()
}
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/ad/fingerprints/ConvertHelpFeedItemListFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/ad/fingerprints/ConvertHelpFeedItemListFingerprint.kt
index fc252a24c..4f68c3819 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/ad/fingerprints/ConvertHelpFeedItemListFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/ad/fingerprints/ConvertHelpFeedItemListFingerprint.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.tiktok.ad.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object ConvertHelpFeedItemListFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/ConvertHelp;") &&
methodDef.name.endsWith("${'$'}FeedItemList")
}
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/ad/fingerprints/FeedItemListCloneFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/ad/fingerprints/FeedItemListCloneFingerprint.kt
index 4f9de5d3a..a3544cb1c 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/ad/fingerprints/FeedItemListCloneFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/ad/fingerprints/FeedItemListCloneFingerprint.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.tiktok.ad.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object FeedItemListCloneFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/FeedItemList;") && methodDef.name == "clone"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/fingerprints/FeedApiServiceLIZFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/fingerprints/FeedApiServiceLIZFingerprint.kt
index 667e5abcd..30854e0c3 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/fingerprints/FeedApiServiceLIZFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/fingerprints/FeedApiServiceLIZFingerprint.kt
@@ -5,8 +5,8 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
object FeedApiServiceLIZFingerprint : MethodFingerprint(
- access = AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.SYNTHETIC,
- customFingerprint = { methodDef ->
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.SYNTHETIC,
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/FeedApiService;") && methodDef.name == "LIZ"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint.kt
index f1e851661..d5219ff3c 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint.kt
@@ -7,7 +7,7 @@ import org.jf.dexlib2.AccessFlags
object ACLCommonShareFingerprint : MethodFingerprint(
"I",
AccessFlags.PUBLIC or AccessFlags.FINAL,
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/ACLCommonShare;") &&
methodDef.name == "getCode"
}
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint2.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint2.kt
index 384530db7..39e1a7171 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint2.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint2.kt
@@ -13,7 +13,7 @@ import org.jf.dexlib2.AccessFlags
object ACLCommonShareFingerprint2 : MethodFingerprint(
"I",
AccessFlags.PUBLIC or AccessFlags.FINAL,
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/ACLCommonShare;") &&
methodDef.name == "getShowType"
}
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint3.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint3.kt
index cf585dd21..13e4d61c5 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint3.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint3.kt
@@ -13,7 +13,7 @@ import org.jf.dexlib2.AccessFlags
object ACLCommonShareFingerprint3 : MethodFingerprint(
"I",
AccessFlags.PUBLIC or AccessFlags.FINAL,
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/ACLCommonShare;") &&
methodDef.name == "getTranscode"
}
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/fingerprints/AwemeGetVideoControlFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/fingerprints/AwemeGetVideoControlFingerprint.kt
index fb6463186..a71d6c887 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/fingerprints/AwemeGetVideoControlFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/fingerprints/AwemeGetVideoControlFingerprint.kt
@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
object AwemeGetVideoControlFingerprint : MethodFingerprint(
"L",
AccessFlags.PUBLIC.value,
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/Aweme;") && methodDef.name == "getVideoControl"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/SpeedControlParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/SpeedControlParentFingerprint.kt
index 4e70ca812..2a395194b 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/SpeedControlParentFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/SpeedControlParentFingerprint.kt
@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
object SpeedControlParentFingerprint : MethodFingerprint(
returnType = "L",
- access = AccessFlags.PRIVATE or AccessFlags.FINAL,
+ accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
parameters = listOf(
"L"
),
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt
index 9afc4eccf..b4d095976 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.tiktok.misc.integrations.fingerprints
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
object InitFingerprint : IntegrationsFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/AwemeHostApplication;") &&
methodDef.name == "onCreate"
}
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/fingerprints/MandatoryLoginServiceFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/fingerprints/MandatoryLoginServiceFingerprint.kt
index 842dcae2d..950c25835 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/fingerprints/MandatoryLoginServiceFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/fingerprints/MandatoryLoginServiceFingerprint.kt
@@ -2,7 +2,7 @@ package app.revanced.patches.tiktok.misc.login.disablerequirement.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object MandatoryLoginServiceFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/MandatoryLoginService;") &&
methodDef.name == "enableForcedLogin"
}
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/fingerprints/MandatoryLoginServiceFingerprint2.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/fingerprints/MandatoryLoginServiceFingerprint2.kt
index 59015a6b6..9f6de329e 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/fingerprints/MandatoryLoginServiceFingerprint2.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/login/disablerequirement/fingerprints/MandatoryLoginServiceFingerprint2.kt
@@ -9,7 +9,7 @@ import app.revanced.patches.tiktok.misc.login.disablerequirement.annotations.Dis
@DisableLoginRequirementCompatibility
@Version("0.0.1")
object MandatoryLoginServiceFingerprint2 : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/MandatoryLoginService;") &&
methodDef.name == "shouldShowForcedLogin"
}
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/fingerprints/GoogleAuthAvailableFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/fingerprints/GoogleAuthAvailableFingerprint.kt
index 2e1a1eaf1..24dd8a7de 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/fingerprints/GoogleAuthAvailableFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/fingerprints/GoogleAuthAvailableFingerprint.kt
@@ -6,9 +6,9 @@ import org.jf.dexlib2.AccessFlags
object GoogleAuthAvailableFingerprint : MethodFingerprint(
returnType = "Z",
- access = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf(),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lcom/bytedance/lobby/google/GoogleAuth;"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/fingerprints/GoogleOneTapAuthAvailableFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/fingerprints/GoogleOneTapAuthAvailableFingerprint.kt
index 26e51a522..fb677fcb6 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/fingerprints/GoogleOneTapAuthAvailableFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/login/fixgoogle/fingerprints/GoogleOneTapAuthAvailableFingerprint.kt
@@ -6,9 +6,9 @@ import org.jf.dexlib2.AccessFlags
object GoogleOneTapAuthAvailableFingerprint : MethodFingerprint(
returnType = "Z",
- access = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf(),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lcom/bytedance/lobby/google/GoogleOneTapAuth;"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/AdPersonalizationActivityOnCreateFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/AdPersonalizationActivityOnCreateFingerprint.kt
index 69778a650..b9b524d6b 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/AdPersonalizationActivityOnCreateFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/AdPersonalizationActivityOnCreateFingerprint.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.tiktok.misc.settings.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object AdPersonalizationActivityOnCreateFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/AdPersonalizationActivity;") &&
methodDef.name == "onCreate"
}
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/SettingsOnViewCreatedFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/SettingsOnViewCreatedFingerprint.kt
index 46f2ba697..a2d655ab3 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/SettingsOnViewCreatedFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/SettingsOnViewCreatedFingerprint.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.tiktok.misc.settings.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object SettingsOnViewCreatedFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/SettingNewVersionFragment;") &&
methodDef.name == "onViewCreated"
}
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/SettingsStatusLoadFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/SettingsStatusLoadFingerprint.kt
index c2f1d3c51..b1e3bb5d0 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/SettingsStatusLoadFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/SettingsStatusLoadFingerprint.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.tiktok.misc.settings.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object SettingsStatusLoadFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("Lapp/revanced/tiktok/settingsmenu/SettingsStatus;") &&
methodDef.name == "load"
}
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/SettingsPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/SettingsPatch.kt
index 0fcd0943d..42cd5a0d5 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/SettingsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/SettingsPatch.kt
@@ -25,7 +25,6 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
import org.jf.dexlib2.iface.reference.StringReference
-import org.jf.dexlib2.iface.reference.TypeReference
@Patch
@DependsOn([IntegrationsPatch::class])
@@ -96,7 +95,7 @@ class SettingsPatch : BytecodePatch(
private fun patchOptionNameAndOnClickEvent(index: Int, context: BytecodeContext) {
with(SettingsOnViewCreatedFingerprint.result!!.mutableMethod) {
// Patch option name
- val overrideRegister = (instruction(index - 4) as OneRegisterInstruction).registerA
+ val overrideRegister = instruction(index - 4).registerA
replaceInstruction(
index - 4,
"""
@@ -105,16 +104,14 @@ class SettingsPatch : BytecodePatch(
)
// Patch option OnClick Event
- with(((instruction(index) as ReferenceInstruction).reference as TypeReference).type) {
- context.findClass(this)!!.mutableClass.methods.first { it.name == "onClick" }
- .addInstructions(
- 0,
- """
- invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsMenu;->startSettingsActivity()V
- return-void
- """
- )
- }
+ val type = instruction(index).reference.toString()
+ context.findClass(type)!!.mutableClass.methods.first { type == "onClick" }.addInstructions(
+ 0,
+ """
+ invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsMenu;->startSettingsActivity()V
+ return-void
+ """
+ )
}
}
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/patch/SpoofSimPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/patch/SpoofSimPatch.kt
index 822a2e2fb..d193ab61d 100644
--- a/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/patch/SpoofSimPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/patch/SpoofSimPatch.kt
@@ -97,14 +97,14 @@ class SpoofSimPatch : BytecodePatch() {
// Patch Android API and return fake sim information
private fun MutableMethod.replaceReference(index: Int, replacement: String) {
- val resultReg = (instruction(index + 1) as OneRegisterInstruction).registerA
+ val resultReg = instruction(index + 1).registerA
addInstructions(
index + 2,
- """
- invoke-static {v$resultReg}, Lapp/revanced/tiktok/spoof/sim/SpoofSimPatch;->$replacement(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v$resultReg
- """
+ """
+ invoke-static {v$resultReg}, Lapp/revanced/tiktok/spoof/sim/SpoofSimPatch;->$replacement(Ljava/lang/String;)Ljava/lang/String;
+ move-result-object v$resultReg
+ """
)
}
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/trakt/annotations/UnlockProCompatibility.kt b/src/main/kotlin/app/revanced/patches/trakt/annotations/UnlockProCompatibility.kt
new file mode 100644
index 000000000..aa619bd8c
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/trakt/annotations/UnlockProCompatibility.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.trakt.annotations
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("tv.trakt.trakt")])
+@Target(AnnotationTarget.CLASS)
+internal annotation class UnlockProCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/trakt/fingerprints/IsVIPEPFingerprint.kt b/src/main/kotlin/app/revanced/patches/trakt/fingerprints/IsVIPEPFingerprint.kt
new file mode 100644
index 000000000..f62cfe5fc
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/trakt/fingerprints/IsVIPEPFingerprint.kt
@@ -0,0 +1,11 @@
+package app.revanced.patches.trakt.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+
+object IsVIPEPFingerprint : MethodFingerprint(
+ customFingerprint = custom@{ methodDef, _ ->
+ if (!methodDef.definingClass.endsWith("RealmUserSettings;")) return@custom false
+
+ methodDef.name == "isVIPEP"
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/trakt/fingerprints/IsVIPFingerprint.kt b/src/main/kotlin/app/revanced/patches/trakt/fingerprints/IsVIPFingerprint.kt
new file mode 100644
index 000000000..eb678d260
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/trakt/fingerprints/IsVIPFingerprint.kt
@@ -0,0 +1,11 @@
+package app.revanced.patches.trakt.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+
+object IsVIPFingerprint : MethodFingerprint(
+ customFingerprint = custom@{ methodDef, _ ->
+ if (!methodDef.definingClass.endsWith("RealmUserSettings;")) return@custom false
+
+ methodDef.name == "isVIP"
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/trakt/fingerprints/RealmUserSettingsFingerprint.kt b/src/main/kotlin/app/revanced/patches/trakt/fingerprints/RealmUserSettingsFingerprint.kt
new file mode 100644
index 000000000..dd8c8198e
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/trakt/fingerprints/RealmUserSettingsFingerprint.kt
@@ -0,0 +1,9 @@
+package app.revanced.patches.trakt.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+
+object RealmUserSettingsFingerprint : MethodFingerprint(
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass.endsWith("RealmUserSettings;")
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/trakt/patch/UnlockProPatch.kt b/src/main/kotlin/app/revanced/patches/trakt/patch/UnlockProPatch.kt
new file mode 100644
index 000000000..362b91335
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/trakt/patch/UnlockProPatch.kt
@@ -0,0 +1,52 @@
+package app.revanced.patches.trakt.patch
+
+import app.revanced.extensions.toErrorResult
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patches.trakt.annotations.UnlockProCompatibility
+import app.revanced.patches.trakt.fingerprints.IsVIPEPFingerprint
+import app.revanced.patches.trakt.fingerprints.IsVIPFingerprint
+import app.revanced.patches.trakt.fingerprints.RealmUserSettingsFingerprint
+
+@Patch
+@Name("unlock-pro")
+@Description("Unlocks pro features.")
+@UnlockProCompatibility
+@Version("0.0.1")
+class UnlockProPatch : BytecodePatch(
+ listOf(RealmUserSettingsFingerprint)
+) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ RealmUserSettingsFingerprint.result?.classDef?.let { realUserSettingsClass ->
+ arrayOf(IsVIPFingerprint, IsVIPEPFingerprint).onEach { fingerprint ->
+ // Resolve both fingerprints on the same class.
+ if (!fingerprint.resolve(context, realUserSettingsClass))
+ throw fingerprint.toErrorResult()
+ }.forEach { fingerprint ->
+ // Return true for both VIP check methods.
+ fingerprint.result?.mutableMethod?.addInstructions(0, RETURN_TRUE_INSTRUCTIONS)
+ ?: return fingerprint.toErrorResult()
+ }
+ } ?: return RealmUserSettingsFingerprint.toErrorResult()
+
+ return PatchResultSuccess()
+ }
+
+ private companion object {
+ const val RETURN_TRUE_INSTRUCTIONS =
+ """
+ const/4 v0, 0x1
+ invoke-static {v0}, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;
+ move-result-object v1
+ return-object v1
+ """
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twelvewidgets/unlock/fingerprints/MethodUnlockFingerprint.kt b/src/main/kotlin/app/revanced/patches/twelvewidgets/unlock/fingerprints/MethodUnlockFingerprint.kt
index c85e6c92e..76821975f 100644
--- a/src/main/kotlin/app/revanced/patches/twelvewidgets/unlock/fingerprints/MethodUnlockFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twelvewidgets/unlock/fingerprints/MethodUnlockFingerprint.kt
@@ -5,7 +5,7 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
abstract class MethodUnlockFingerprint(private val className: String) : MethodFingerprint(
"L",
strings = listOf("binding.addButton"),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/$className;")
}
)
diff --git a/src/main/kotlin/app/revanced/patches/twelvewidgets/unlock/patch/UnlockPaidWidgetsPatch.kt b/src/main/kotlin/app/revanced/patches/twelvewidgets/unlock/patch/UnlockPaidWidgetsPatch.kt
index 8a188600f..16455a4c5 100644
--- a/src/main/kotlin/app/revanced/patches/twelvewidgets/unlock/patch/UnlockPaidWidgetsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twelvewidgets/unlock/patch/UnlockPaidWidgetsPatch.kt
@@ -38,7 +38,7 @@ class UnlockPaidWidgetsPatch : BytecodePatch(
fingerprint.result?.mutableMethod ?: return fingerprint.toErrorResult()
}.forEach { method ->
method.apply {
- removeInstructions(4, 2)
+ removeInstructions(4, 3)
addInstructions(
implementation?.instructions?.size!!, """
const/4 v1, 0x0
diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/audio/fingerprints/AudioAdsPresenterPlayFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/audio/fingerprints/AudioAdsPresenterPlayFingerprint.kt
index 56bdf6286..fc7192cc1 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/audio/fingerprints/AudioAdsPresenterPlayFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/ad/audio/fingerprints/AudioAdsPresenterPlayFingerprint.kt
@@ -4,7 +4,7 @@ package app.revanced.patches.twitch.ad.audio.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object AudioAdsPresenterPlayFingerprint : MethodFingerprint(
- customFingerprint = { method ->
+ customFingerprint = { method, _ ->
method.definingClass.endsWith("AudioAdsPlayerPresenter;") && method.name == "playAd"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/audio/patch/AudioAdsPatch.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/audio/patch/AudioAdsPatch.kt
index a5cccb1c7..74cbff08b 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/audio/patch/AudioAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/ad/audio/patch/AudioAdsPatch.kt
@@ -50,7 +50,6 @@ class AudioAdsPatch : BytecodePatch(
"revanced_block_audio_ads",
"Block audio ads"
),
- true,
StringResource(
"revanced_block_audio_ads_on",
"Audio ads are blocked"
@@ -59,6 +58,7 @@ class AudioAdsPatch : BytecodePatch(
"revanced_block_audio_ads_off",
"Audio ads are unblocked"
),
+ default = true,
)
)
diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/fingerprints/CreateUsherClientFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/fingerprints/CreateUsherClientFingerprint.kt
index 348044040..d47628827 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/fingerprints/CreateUsherClientFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/fingerprints/CreateUsherClientFingerprint.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.twitch.ad.embedded.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object CreateUsherClientFingerprint : MethodFingerprint(
- customFingerprint = { method ->
+ customFingerprint = { method, _ ->
method.definingClass.endsWith("Ltv/twitch/android/network/OkHttpClientFactory;") && method.name == "buildOkHttpClient"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/patch/EmbeddedAdsPatch.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/patch/EmbeddedAdsPatch.kt
index 5384546a4..23debc540 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/patch/EmbeddedAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/ad/embedded/patch/EmbeddedAdsPatch.kt
@@ -66,7 +66,7 @@ class EmbeddedAdsPatch : BytecodePatch(
StringResource("key_revanced_proxy_purpleadblock", "purpleadblock")
)
),
- "ttv-lol"
+ default = "ttv-lol"
)
)
diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/CheckAdEligibilityLambdaFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/CheckAdEligibilityLambdaFingerprint.kt
index 04c1c09b1..31ea27485 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/CheckAdEligibilityLambdaFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/CheckAdEligibilityLambdaFingerprint.kt
@@ -8,7 +8,7 @@ object CheckAdEligibilityLambdaFingerprint : MethodFingerprint(
"L",
AccessFlags.PRIVATE or AccessFlags.FINAL or AccessFlags.STATIC,
listOf("L", "L", "L"),
- customFingerprint = { method ->
+ customFingerprint = { method, _ ->
method.definingClass.endsWith("AdEligibilityFetcher;") &&
method.name.contains("shouldRequestAd")
}
diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/ContentConfigShowAdsFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/ContentConfigShowAdsFingerprint.kt
index ed38035eb..f64ba6ffe 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/ContentConfigShowAdsFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/ContentConfigShowAdsFingerprint.kt
@@ -4,7 +4,7 @@ package app.revanced.patches.twitch.ad.video.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object ContentConfigShowAdsFingerprint : MethodFingerprint(
- customFingerprint = { method ->
+ customFingerprint = { method, _ ->
method.definingClass.endsWith("ContentConfigData;") && method.name == "getShowAds"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/GetReadyToShowAdFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/GetReadyToShowAdFingerprint.kt
index 3256ad024..0f7b2454c 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/GetReadyToShowAdFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/GetReadyToShowAdFingerprint.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.twitch.ad.video.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object GetReadyToShowAdFingerprint : MethodFingerprint(
- customFingerprint = { method ->
+ customFingerprint = { method, _ ->
method.definingClass.endsWith("/StreamDisplayAdsPresenter;") && method.name == "getReadyToShowAdOrAbort"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/video/patch/VideoAdsPatch.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/video/patch/VideoAdsPatch.kt
index 9b1197e78..8094c03f5 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/ad/video/patch/VideoAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/ad/video/patch/VideoAdsPatch.kt
@@ -132,7 +132,6 @@ class VideoAdsPatch : AbstractAdPatch(
"revanced_block_video_ads",
"Block video ads"
),
- true,
StringResource(
"revanced_block_video_ads_on",
"Video ads are blocked"
@@ -141,6 +140,7 @@ class VideoAdsPatch : AbstractAdPatch(
"revanced_block_video_ads_off",
"Video ads are unblocked"
),
+ default = true
)
)
diff --git a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/ChatUtilCreateDeletedSpanFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/ChatUtilCreateDeletedSpanFingerprint.kt
index 733710b2b..5d5bfe492 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/ChatUtilCreateDeletedSpanFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/ChatUtilCreateDeletedSpanFingerprint.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.twitch.chat.antidelete.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object ChatUtilCreateDeletedSpanFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/ChatUtil\$Companion;") && methodDef.name == "createDeletedSpanFromChatMessageSpan"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/DeletedMessageClickableSpanCtorFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/DeletedMessageClickableSpanCtorFingerprint.kt
index 6ecb63cbd..49e02dd7a 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/DeletedMessageClickableSpanCtorFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/DeletedMessageClickableSpanCtorFingerprint.kt
@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
object DeletedMessageClickableSpanCtorFingerprint : MethodFingerprint(
"V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("DeletedMessageClickableSpan;")
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/SetHasModAccessFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/SetHasModAccessFingerprint.kt
index 7e8ee66a3..12ca4da9f 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/SetHasModAccessFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/SetHasModAccessFingerprint.kt
@@ -4,7 +4,7 @@ package app.revanced.patches.twitch.chat.antidelete.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object SetHasModAccessFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("DeletedMessageClickableSpan;") && methodDef.name == "setHasModAccess"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/patch/ShowDeletedMessagesPatch.kt b/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/patch/ShowDeletedMessagesPatch.kt
index dba6e833e..dd69b4da1 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/patch/ShowDeletedMessagesPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/patch/ShowDeletedMessagesPatch.kt
@@ -4,8 +4,12 @@ import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.*
-import app.revanced.patcher.patch.*
+import app.revanced.patcher.extensions.addInstruction
+import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.extensions.instruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.smali.ExternalLabel
@@ -13,7 +17,9 @@ import app.revanced.patches.shared.settings.preference.impl.ArrayResource
import app.revanced.patches.shared.settings.preference.impl.ListPreference
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.twitch.chat.antidelete.annotations.ShowDeletedMessagesCompatibility
-import app.revanced.patches.twitch.chat.antidelete.fingerprints.*
+import app.revanced.patches.twitch.chat.antidelete.fingerprints.ChatUtilCreateDeletedSpanFingerprint
+import app.revanced.patches.twitch.chat.antidelete.fingerprints.DeletedMessageClickableSpanCtorFingerprint
+import app.revanced.patches.twitch.chat.antidelete.fingerprints.SetHasModAccessFingerprint
import app.revanced.patches.twitch.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.twitch.misc.settings.bytecode.patch.SettingsPatch
@@ -92,7 +98,7 @@ class ShowDeletedMessagesPatch : BytecodePatch(
StringResource("key_revanced_deleted_messages_cross_out", "cross-out")
)
),
- "cross-out"
+ default = "cross-out"
)
)
diff --git a/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/annotations/AutoClaimChannelPointsCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/annotations/AutoClaimChannelPointsCompatibility.kt
new file mode 100644
index 000000000..30473cf3a
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/annotations/AutoClaimChannelPointsCompatibility.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.twitch.chat.autoclaim.annotations
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("tv.twitch.android.app")])
+@Target(AnnotationTarget.CLASS)
+internal annotation class AutoClaimChannelPointsCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/fingerprints/CommunityPointsButtonViewDelegateFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/fingerprints/CommunityPointsButtonViewDelegateFingerprint.kt
new file mode 100644
index 000000000..5bbfaeb00
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/fingerprints/CommunityPointsButtonViewDelegateFingerprint.kt
@@ -0,0 +1,10 @@
+package app.revanced.patches.twitch.chat.autoclaim.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+
+object CommunityPointsButtonViewDelegateFingerprint : MethodFingerprint(
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass.endsWith("CommunityPointsButtonViewDelegate;")
+ && methodDef.name == "showClaimAvailable"
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/patch/AutoClaimChannelPointsPatch.kt b/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/patch/AutoClaimChannelPointsPatch.kt
new file mode 100644
index 000000000..210a4950b
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/twitch/chat/autoclaim/patch/AutoClaimChannelPointsPatch.kt
@@ -0,0 +1,70 @@
+package app.revanced.patches.twitch.chat.autoclaim.patch
+
+import app.revanced.extensions.toErrorResult
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.extensions.instruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.util.smali.ExternalLabel
+import app.revanced.patches.shared.settings.preference.impl.StringResource
+import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
+import app.revanced.patches.twitch.chat.autoclaim.annotations.AutoClaimChannelPointsCompatibility
+import app.revanced.patches.twitch.chat.autoclaim.fingerprints.CommunityPointsButtonViewDelegateFingerprint
+import app.revanced.patches.twitch.misc.settings.bytecode.patch.SettingsPatch
+
+@Patch
+@DependsOn([SettingsPatch::class])
+@Name("auto-claim-channel-points")
+@Description("Automatically claim Channel Points.")
+@AutoClaimChannelPointsCompatibility
+@Version("0.0.1")
+class AutoClaimChannelPointPatch : BytecodePatch(
+ listOf(CommunityPointsButtonViewDelegateFingerprint)
+) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ SettingsPatch.PreferenceScreen.CHAT.GENERAL.addPreferences(
+ SwitchPreference(
+ "revanced_auto_claim_channel_points",
+ StringResource(
+ "revanced_auto_claim_channel_points",
+ "Automatically claim Channel Points"
+ ),
+ StringResource(
+ "revanced_auto_claim_channel_points_on",
+ "Channel Points are claimed automatically"
+ ),
+ StringResource(
+ "revanced_auto_claim_channel_points_off",
+ "Channel Points are not claimed automatically"
+ ),
+ default = true
+ )
+ )
+
+ CommunityPointsButtonViewDelegateFingerprint.result?.mutableMethod?.apply {
+ val lastIndex = implementation!!.instructions.lastIndex
+ addInstructions(
+ lastIndex, // place in front of return-void
+ """
+ invoke-static {}, Lapp/revanced/twitch/patches/AutoClaimChannelPointsPatch;->shouldAutoClaim()Z
+ move-result v0
+ if-eqz v0, :auto_claim
+
+ # Claim by calling the button's onClick method
+
+ iget-object v0, p0, Ltv/twitch/android/shared/community/points/viewdelegate/CommunityPointsButtonViewDelegate;->buttonLayout:Landroid/view/ViewGroup;
+ invoke-virtual { v0 }, Landroid/view/View;->callOnClick()Z
+ """,
+ listOf(ExternalLabel("auto_claim", instruction(lastIndex)))
+ )
+ } ?: return CommunityPointsButtonViewDelegateFingerprint.toErrorResult()
+ return PatchResultSuccess()
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsDebugConfigEnabledFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsDebugConfigEnabledFingerprint.kt
index e7a317849..145bc06be 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsDebugConfigEnabledFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsDebugConfigEnabledFingerprint.kt
@@ -4,7 +4,7 @@ package app.revanced.patches.twitch.debug.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object IsDebugConfigEnabledFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("BuildConfigUtil;") && methodDef.name == "isDebugConfigEnabled"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsOmVerificationEnabledFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsOmVerificationEnabledFingerprint.kt
index cf8f1f759..ab50280a5 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsOmVerificationEnabledFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsOmVerificationEnabledFingerprint.kt
@@ -4,7 +4,7 @@ package app.revanced.patches.twitch.debug.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object IsOmVerificationEnabledFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("BuildConfigUtil;") && methodDef.name == "isOmVerificationEnabled"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/ShouldShowDebugOptionsFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/ShouldShowDebugOptionsFingerprint.kt
index 12c5de043..e9a77cc3b 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/ShouldShowDebugOptionsFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/ShouldShowDebugOptionsFingerprint.kt
@@ -4,7 +4,7 @@ package app.revanced.patches.twitch.debug.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object ShouldShowDebugOptionsFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("BuildConfigUtil;") && methodDef.name == "shouldShowDebugOptions"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/debug/patch/DebugModePatch.kt b/src/main/kotlin/app/revanced/patches/twitch/debug/patch/DebugModePatch.kt
index 755efe696..5c864ba8b 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/debug/patch/DebugModePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/debug/patch/DebugModePatch.kt
@@ -59,7 +59,6 @@ class DebugModePatch : BytecodePatch(
"revanced_debug_mode_enable",
"Enable debug mode"
),
- false,
StringResource(
"revanced_debug_mode_on",
"Debug mode is enabled (not recommended)"
@@ -68,6 +67,7 @@ class DebugModePatch : BytecodePatch(
"revanced_debug_mode_off",
"Debug mode is disabled"
),
+ default = false,
)
)
diff --git a/src/main/kotlin/app/revanced/patches/twitch/misc/integrations/fingerprints/InitFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/misc/integrations/fingerprints/InitFingerprint.kt
index 7f55dd22f..258db9902 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/misc/integrations/fingerprints/InitFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/misc/integrations/fingerprints/InitFingerprint.kt
@@ -9,7 +9,7 @@ import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.
@IntegrationsCompatibility
@Version("0.0.1")
object InitFingerprint : IntegrationsFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/TwitchApplication;") &&
methodDef.name == "onCreate"
}
diff --git a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/bytecode/patch/SettingsPatch.kt b/src/main/kotlin/app/revanced/patches/twitch/misc/settings/bytecode/patch/SettingsPatch.kt
index d0f8b7214..f700354f7 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/bytecode/patch/SettingsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/misc/settings/bytecode/patch/SettingsPatch.kt
@@ -4,7 +4,9 @@ import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.*
+import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.extensions.instruction
+import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
@@ -18,8 +20,10 @@ import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.util.AbstractPreferenceScreen
import app.revanced.patches.twitch.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.twitch.misc.settings.annotations.SettingsCompatibility
-import app.revanced.patches.twitch.misc.settings.components.CustomPreferenceCategory
-import app.revanced.patches.twitch.misc.settings.fingerprints.*
+import app.revanced.patches.twitch.misc.settings.fingerprints.MenuGroupsOnClickFingerprint
+import app.revanced.patches.twitch.misc.settings.fingerprints.MenuGroupsUpdatedFingerprint
+import app.revanced.patches.twitch.misc.settings.fingerprints.SettingsActivityOnCreateFingerprint
+import app.revanced.patches.twitch.misc.settings.fingerprints.SettingsMenuItemEnumFingerprint
import app.revanced.patches.twitch.misc.settings.resource.patch.SettingsResourcePatch
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.immutable.ImmutableField
@@ -178,10 +182,11 @@ class SettingsPatch : BytecodePatch(
internal inner class CustomCategory(key: String, title: String) : Screen.Category(key, title) {
/* For Twitch, we need to load our CustomPreferenceCategory class instead of the default one. */
override fun transform(): PreferenceCategory {
- return CustomPreferenceCategory(
+ return PreferenceCategory(
key,
StringResource("${key}_title", title),
- preferences.sortedBy { it.title.value }
+ preferences.sortedBy { it.title.value },
+ "app.revanced.twitch.settingsmenu.preference.CustomPreferenceCategory"
)
}
}
diff --git a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/components/CustomPreferenceCategory.kt b/src/main/kotlin/app/revanced/patches/twitch/misc/settings/components/CustomPreferenceCategory.kt
deleted file mode 100644
index 20c7bdb80..000000000
--- a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/components/CustomPreferenceCategory.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package app.revanced.patches.twitch.misc.settings.components
-
-import app.revanced.patches.shared.settings.preference.BasePreference
-import app.revanced.patches.shared.settings.preference.impl.PreferenceCategory
-import app.revanced.patches.shared.settings.preference.impl.StringResource
-
-/**
- * Customized preference category for Twitch.
- *
- * @param key The key of the preference.
- * @param title The title of the preference.
- * @param preferences Child preferences of this category.
- */
-internal open class CustomPreferenceCategory(
- key: String,
- title: StringResource,
- preferences: List
-) : PreferenceCategory(key, title, preferences) {
- override val tag: String = "app.revanced.twitch.settingsmenu.preference.CustomPreferenceCategory"
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/fingerprints/MenuGroupsOnClickFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/misc/settings/fingerprints/MenuGroupsOnClickFingerprint.kt
index 1a6375986..6bf971dd6 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/fingerprints/MenuGroupsOnClickFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/misc/settings/fingerprints/MenuGroupsOnClickFingerprint.kt
@@ -8,7 +8,7 @@ object MenuGroupsOnClickFingerprint : MethodFingerprint(
"V",
AccessFlags.PRIVATE or AccessFlags.STATIC or AccessFlags.FINAL,
listOf("L", "L", "L"),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/SettingsMenuViewDelegate;")
&& methodDef.name.contains("render")
}
diff --git a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/fingerprints/MenuGroupsUpdatedFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/misc/settings/fingerprints/MenuGroupsUpdatedFingerprint.kt
index 913f31d14..42cc4e466 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/fingerprints/MenuGroupsUpdatedFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/misc/settings/fingerprints/MenuGroupsUpdatedFingerprint.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.twitch.misc.settings.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object MenuGroupsUpdatedFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/SettingsMenuPresenter\$Event\$MenuGroupsUpdated;")
&& methodDef.name == ""
}
diff --git a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/fingerprints/SettingsActivityOnCreateFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/misc/settings/fingerprints/SettingsActivityOnCreateFingerprint.kt
index f976f0210..ed30aa4eb 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/fingerprints/SettingsActivityOnCreateFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/misc/settings/fingerprints/SettingsActivityOnCreateFingerprint.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.twitch.misc.settings.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object SettingsActivityOnCreateFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/SettingsActivity;") &&
methodDef.name == "onCreate"
}
diff --git a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/fingerprints/SettingsMenuItemEnumFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/misc/settings/fingerprints/SettingsMenuItemEnumFingerprint.kt
index cdb2dd177..cbee9a584 100644
--- a/src/main/kotlin/app/revanced/patches/twitch/misc/settings/fingerprints/SettingsMenuItemEnumFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitch/misc/settings/fingerprints/SettingsMenuItemEnumFingerprint.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.twitch.misc.settings.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object SettingsMenuItemEnumFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/SettingsMenuItem;") && methodDef.name == ""
}
)
diff --git a/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/fingerprints/InlineActionTypesFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/fingerprints/InlineActionTypesFingerprint.kt
index eb4f86a25..8cb634e7d 100644
--- a/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/fingerprints/InlineActionTypesFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/fingerprints/InlineActionTypesFingerprint.kt
@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
object InlineActionTypesFingerprint : MethodFingerprint(
returnType = "Ljava/util/List",
- access = AccessFlags.PUBLIC or AccessFlags.STATIC,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
strings = listOf(
"getCurrentMemoizing()",
"android_animated_reply_icon_enabled",
diff --git a/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/fingerprints/TweetStatsContainerConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/fingerprints/TweetStatsContainerConstructorFingerprint.kt
index dda7c74cc..811dd497e 100644
--- a/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/fingerprints/TweetStatsContainerConstructorFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/fingerprints/TweetStatsContainerConstructorFingerprint.kt
@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
object TweetStatsContainerConstructorFingerprint : MethodFingerprint(
- access = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
parameters = listOf("L"),
opcodes = listOf(
Opcode.INVOKE_DIRECT,
diff --git a/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/fingerprints/TweetStatsContainerWrapperConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/fingerprints/TweetStatsContainerWrapperConstructorFingerprint.kt
index 791e15162..3c93ceda6 100644
--- a/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/fingerprints/TweetStatsContainerWrapperConstructorFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/fingerprints/TweetStatsContainerWrapperConstructorFingerprint.kt
@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
object TweetStatsContainerWrapperConstructorFingerprint : MethodFingerprint(
- access = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
parameters = listOf("L"),
opcodes = listOf(
Opcode.INVOKE_DIRECT,
diff --git a/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/fingerprints/TweetStatsViewDelegateBinderFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/fingerprints/TweetStatsViewDelegateBinderFingerprint.kt
index 3d3f845b4..970f7e81b 100644
--- a/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/fingerprints/TweetStatsViewDelegateBinderFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/fingerprints/TweetStatsViewDelegateBinderFingerprint.kt
@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
object TweetStatsViewDelegateBinderFingerprint : MethodFingerprint(
- access = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
opcodes = listOf(
Opcode.NEW_INSTANCE,
Opcode.CONST_16,
diff --git a/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/patch/HideViewsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/patch/HideViewsBytecodePatch.kt
index 3752d0798..b8cb63652 100644
--- a/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/patch/HideViewsBytecodePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitter/layout/hideviews/patch/HideViewsBytecodePatch.kt
@@ -61,7 +61,7 @@ class HideViewsBytecodePatch : BytecodePatch(
TweetStatsContainerConstructorFingerprint,
returnFingerprint
) { patternScanResult, method ->
- method.removeInstructions(patternScanResult.endIndex - 3, 2)
+ method.removeInstructions(patternScanResult.endIndex - 3, 3)
}
}
@@ -80,13 +80,13 @@ class HideViewsBytecodePatch : BytecodePatch(
TweetStatsContainerWrapperConstructorFingerprint,
wrapperReturnFingerprint
) { patternScanResult, method ->
- method.removeInstructions(patternScanResult.startIndex - 4, 3)
+ method.removeInstructions(patternScanResult.startIndex - 4, 4)
}
}
private fun removeViewDelegateBinderSubscription() {
transformMethod(TweetStatsViewDelegateBinderFingerprint) { result, method ->
- method.removeInstructions(result.scanResult.patternScanResult!!.startIndex - 4, 9)
+ method.removeInstructions(result.scanResult.patternScanResult!!.startIndex - 4, 10)
}
}
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/fingerprints/JsonHookPatchFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/fingerprints/JsonHookPatchFingerprint.kt
index cc533162d..732e7fb6f 100644
--- a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/fingerprints/JsonHookPatchFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/fingerprints/JsonHookPatchFingerprint.kt
@@ -4,6 +4,10 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode
object JsonHookPatchFingerprint : MethodFingerprint(
- customFingerprint = { methodDef -> methodDef.name == "" },
- opcodes = listOf(Opcode.IGET_OBJECT)
+ customFingerprint = { methodDef, _ -> methodDef.name == "" },
+ opcodes = listOf(
+ Opcode.INVOKE_INTERFACE, // Add dummy hook to hooks list.
+ // Add hooks to the hooks list.
+ Opcode.INVOKE_STATIC // Call buildList.
+ )
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/fingerprints/JsonInputStreamFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/fingerprints/JsonInputStreamFingerprint.kt
index 7c80f5bde..f8f1b4c8d 100644
--- a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/fingerprints/JsonInputStreamFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/fingerprints/JsonInputStreamFingerprint.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.twitter.misc.hook.json.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object JsonInputStreamFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
if (methodDef.parameterTypes.size == 0) false
else methodDef.parameterTypes.first() == "Ljava/io/InputStream;"
}
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/fingerprints/LoganSquareFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/fingerprints/LoganSquareFingerprint.kt
index 98f0a82f6..5eb6f5aec 100644
--- a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/fingerprints/LoganSquareFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/fingerprints/LoganSquareFingerprint.kt
@@ -3,5 +3,5 @@ package app.revanced.patches.twitter.misc.hook.json.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object LoganSquareFingerprint : MethodFingerprint(
- customFingerprint = { methodDef -> methodDef.definingClass.endsWith("LoganSquare;") }
+ customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("LoganSquare;") }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/patch/JsonHookPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/patch/JsonHookPatch.kt
index c604c6810..8a14dc9ce 100644
--- a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/patch/JsonHookPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/patch/JsonHookPatch.kt
@@ -5,13 +5,18 @@ import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.extensions.removeInstructions
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
-import app.revanced.patcher.patch.*
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultError
+import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.RequiresIntegrations
import app.revanced.patches.twitter.misc.hook.json.fingerprints.JsonHookPatchFingerprint
import app.revanced.patches.twitter.misc.hook.json.fingerprints.JsonInputStreamFingerprint
import app.revanced.patches.twitter.misc.hook.json.fingerprints.LoganSquareFingerprint
+import java.io.Closeable
import java.io.InvalidClassException
@Name("json-hook")
@@ -20,16 +25,16 @@ import java.io.InvalidClassException
@RequiresIntegrations
class JsonHookPatch : BytecodePatch(
listOf(LoganSquareFingerprint)
-) {
+), Closeable {
override fun execute(context: BytecodeContext): PatchResult {
- // Make sure the integrations are present.
- val jsonHookPatch = context.findClass { it.type == JSON_HOOK_PATCH_CLASS_DESCRIPTOR }
- ?: return PatchResultError("Could not find integrations.")
+ JsonHookPatchFingerprint.also {
+ // Make sure the integrations are present.
+ val jsonHookPatch = context.findClass { classDef -> classDef.type == JSON_HOOK_PATCH_CLASS_DESCRIPTOR }
+ ?: throw PatchResultError("Could not find integrations.")
- // Allow patch to inject hooks into the patches integrations.
- jsonHookPatchFingerprintResult = JsonHookPatchFingerprint.also {
- it.resolve(context, jsonHookPatch.immutableClass)
- }.result ?: return PatchResultError("Unexpected integrations.")
+ if (!it.resolve(context, jsonHookPatch.immutableClass))
+ throw PatchResultError("Unexpected integrations.")
+ }.let { hooks = JsonHookPatchHook(it) }
// Conveniently find the type to hook a method in, via a named field.
val jsonFactory = LoganSquareFingerprint.result
@@ -64,30 +69,10 @@ class JsonHookPatch : BytecodePatch(
*
* @param context The [BytecodeContext] of the current patch.
* @param descriptor The class descriptor of the hook.
+ * @throws ClassNotFoundException If the class could not be found.
*/
- internal class Hook(context: BytecodeContext, private val descriptor: String) {
- private var added = false
-
- /**
- * Add the hook.
- */
- internal fun add() {
- if (added) return
-
- jsonHookPatchFingerprintResult.apply {
- mutableMethod.apply {
- addInstructions(
- scanResult.patternScanResult!!.startIndex,
- """
- sget-object v1, $descriptor->INSTANCE:$descriptor
- invoke-virtual {v0, v1}, Lkotlin/collections/builders/ListBuilder;->add(Ljava/lang/Object;)Z
- """
- )
- }
- }
-
- added = true
- }
+ internal class Hook(context: BytecodeContext, internal val descriptor: String) {
+ internal var added = false
init {
context.findClass { it.type == descriptor }?.let {
@@ -102,15 +87,67 @@ class JsonHookPatch : BytecodePatch(
}
}
- private companion object {
- const val JSON_HOOK_CLASS_NAMESPACE = "app/revanced/twitter/patches/hook/json"
+ /**
+ * A hook for the [JsonHookPatch].
+ *
+ * @param jsonHookPatchFingerprint The [JsonHookPatchFingerprint] to hook.
+ */
+ internal class JsonHookPatchHook(jsonHookPatchFingerprint: MethodFingerprint): Closeable {
+ private val jsonHookPatchFingerprintResult = jsonHookPatchFingerprint.result!!
+ private val jsonHookPatchIndex = jsonHookPatchFingerprintResult.scanResult.patternScanResult!!.endIndex
- const val JSON_HOOK_PATCH_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/JsonHookPatch;"
+ /**
+ * Add a hook to the [JsonHookPatch].
+ * Will not add the hook if it's already added.
+ *
+ * @param hook The [Hook] to add.
+ */
+ fun addHook(hook: Hook) {
+ if (hook.added) return
- const val BASE_PATCH_CLASS_NAME = "BaseJsonHook"
+ jsonHookPatchFingerprintResult.mutableMethod.apply {
+ // Insert hooks right before calling buildList.
+ val insertIndex = jsonHookPatchIndex
- const val JSON_HOOK_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/$BASE_PATCH_CLASS_NAME;"
+ addInstructions(
+ insertIndex,
+ """
+ sget-object v1, ${hook.descriptor}->INSTANCE:${hook.descriptor}
+ invoke-interface {v0, v1}, Ljava/util/List;->add(Ljava/lang/Object;)Z
+ """
+ )
+ }
- private lateinit var jsonHookPatchFingerprintResult: MethodFingerprintResult
+ hook.added = true
+ }
+
+ override fun close() {
+ // Remove hooks.add(dummyHook).
+ jsonHookPatchFingerprintResult.mutableMethod.apply {
+ val addDummyHookIndex = jsonHookPatchIndex - 2
+
+ removeInstructions(addDummyHookIndex, 2)
+ }
+ }
}
+
+ override fun close() = hooks.close()
+
+ internal companion object {
+ private const val JSON_HOOK_CLASS_NAMESPACE = "app/revanced/twitter/patches/hook/json"
+
+ private const val JSON_HOOK_PATCH_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/JsonHookPatch;"
+
+ private const val BASE_PATCH_CLASS_NAME = "BaseJsonHook"
+
+ private const val JSON_HOOK_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/$BASE_PATCH_CLASS_NAME;"
+
+ /**
+ * The [JsonHookPatchHook] of the [JsonHookPatch].
+ *
+ * @see JsonHookPatchHook
+ */
+ internal lateinit var hooks: JsonHookPatchHook
+ }
+
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/BaseHookPatchPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/BaseHookPatchPatch.kt
index f2dec2a20..4b71bc2ab 100644
--- a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/BaseHookPatchPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/BaseHookPatchPatch.kt
@@ -4,13 +4,13 @@ import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
-import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.twitter.misc.hook.json.patch.JsonHookPatch
-@DependsOn([JsonHookPatch::class])
abstract class BaseHookPatchPatch(private val hookClassDescriptor: String) : BytecodePatch() {
override fun execute(context: BytecodeContext) = try {
- PatchResultSuccess().also { JsonHookPatch.Hook(context, hookClassDescriptor).add() }
+ JsonHookPatch.hooks.addHook(JsonHookPatch.Hook(context, hookClassDescriptor))
+
+ PatchResultSuccess()
} catch (ex: Exception) {
PatchResultError(ex)
}
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/ads/annotations/HideAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/ads/annotations/HideAdsCompatibility.kt
index cdfab469e..d44fa95e0 100644
--- a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/ads/annotations/HideAdsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/ads/annotations/HideAdsCompatibility.kt
@@ -3,10 +3,6 @@ package app.revanced.patches.twitter.misc.hook.patch.ads.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.twitter.android"
- )]
-)
+@Compatibility([Package("com.twitter.android")])
@Target(AnnotationTarget.CLASS)
internal annotation class HideAdsCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/ads/patch/HideAdsPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/ads/patch/HideAdsPatch.kt
index 6273a26d8..36b546014 100644
--- a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/ads/patch/HideAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/ads/patch/HideAdsPatch.kt
@@ -15,8 +15,4 @@ import app.revanced.patches.twitter.misc.hook.patch.ads.annotations.HideAdsCompa
@Description("Hides ads.")
@HideAdsCompatibility
@Version("0.0.1")
-class HideAdsPatch : BaseHookPatchPatch(HOOK_CLASS_DESCRIPTOR) {
- private companion object {
- const val HOOK_CLASS_DESCRIPTOR = "Lapp/revanced/twitter/patches/hook/patch/ads/AdsHook;"
- }
-}
\ No newline at end of file
+class HideAdsPatch : BaseHookPatchPatch("Lapp/revanced/twitter/patches/hook/patch/ads/AdsHook;")
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/recommendation/annotations/HideRecommendedUsersCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/recommendation/annotations/HideRecommendedUsersCompatibility.kt
index cac83ff82..196482e91 100644
--- a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/recommendation/annotations/HideRecommendedUsersCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/recommendation/annotations/HideRecommendedUsersCompatibility.kt
@@ -3,10 +3,6 @@ package app.revanced.patches.twitter.misc.hook.patch.recommendation.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.twitter.android"
- )]
-)
+@Compatibility([Package("com.twitter.android")])
@Target(AnnotationTarget.CLASS)
internal annotation class HideRecommendedUsersCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/recommendation/patch/HideRecommendedUsersPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/recommendation/patch/HideRecommendedUsersPatch.kt
index a6ea294fb..d38ab4893 100644
--- a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/recommendation/patch/HideRecommendedUsersPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/recommendation/patch/HideRecommendedUsersPatch.kt
@@ -15,9 +15,6 @@ import app.revanced.patches.twitter.misc.hook.patch.recommendation.annotations.H
@Description("Hides recommended users.")
@HideRecommendedUsersCompatibility
@Version("0.0.1")
-class HideRecommendedUsersPatch : BaseHookPatchPatch(HOOK_CLASS_DESCRIPTOR) {
- private companion object {
- const val HOOK_CLASS_DESCRIPTOR =
- "Lapp/revanced/twitter/patches/hook/patch/recommendation/RecommendedUsersHook;"
- }
-}
\ No newline at end of file
+class HideRecommendedUsersPatch : BaseHookPatchPatch(
+ "Lapp/revanced/twitter/patches/hook/patch/recommendation/RecommendedUsersHook;"
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/vsco/misc/pro/fingerprints/RevCatSubscriptionFingerprint.kt b/src/main/kotlin/app/revanced/patches/vsco/misc/pro/fingerprints/RevCatSubscriptionFingerprint.kt
new file mode 100644
index 000000000..871b6dcf0
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/vsco/misc/pro/fingerprints/RevCatSubscriptionFingerprint.kt
@@ -0,0 +1,11 @@
+package app.revanced.patches.vsco.misc.pro.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+
+object RevCatSubscriptionFingerprint : MethodFingerprint(
+ returnType = "V",
+ strings = listOf("use_debug_subscription_settings"),
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass.endsWith("/RevCatSubscriptionSettingsRepository;")
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/vsco/misc/pro/patch/UnlockProPatch.kt b/src/main/kotlin/app/revanced/patches/vsco/misc/pro/patch/UnlockProPatch.kt
new file mode 100644
index 000000000..1b428ba4b
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/vsco/misc/pro/patch/UnlockProPatch.kt
@@ -0,0 +1,35 @@
+package app.revanced.patches.vsco.misc.pro.patch
+
+import app.revanced.extensions.toErrorResult
+import app.revanced.patcher.annotation.*
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patches.vsco.misc.pro.fingerprints.RevCatSubscriptionFingerprint
+
+
+@Patch
+@Name("unlock-pro")
+@Description("Unlocks pro features.")
+@Compatibility([Package("com.vsco.cam")])
+@Version("0.0.1")
+class UnlockProPatch : BytecodePatch(
+ listOf(RevCatSubscriptionFingerprint)
+) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ RevCatSubscriptionFingerprint.result?.mutableMethod?.apply {
+ // Set isSubscribed to true.
+ addInstructions(
+ 0,
+ """
+ const p1, 0x1
+ """
+ )
+ } ?: return RevCatSubscriptionFingerprint.toErrorResult()
+
+ return PatchResultSuccess()
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/fingerprints/PromoCodeUnlockFingerprint.kt b/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/fingerprints/PromoCodeUnlockFingerprint.kt
index a0eb98d7e..31f02ab5e 100644
--- a/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/fingerprints/PromoCodeUnlockFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/fingerprints/PromoCodeUnlockFingerprint.kt
@@ -2,7 +2,7 @@ package app.revanced.patches.warnwetter.misc.promocode.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object PromoCodeUnlockFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("PromoTokenVerification;") && methodDef.name == "isValid"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/fingerprints/CheckProFingerprint.kt b/src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/fingerprints/CheckProFingerprint.kt
index 230f83a1e..353aa6a4e 100644
--- a/src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/fingerprints/CheckProFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/windyapp/misc/unlockpro/fingerprints/CheckProFingerprint.kt
@@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object CheckProFingerprint : MethodFingerprint(
"I",
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("RawUserData;") && methodDef.name == "isPro"
}
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/general/annotation/GeneralAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/general/annotation/GeneralAdsCompatibility.kt
deleted file mode 100644
index 65931d8c9..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/ad/general/annotation/GeneralAdsCompatibility.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package app.revanced.patches.youtube.ad.general.annotation
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class GeneralAdsCompatibility
-
diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/general/annotation/HideAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/general/annotation/HideAdsCompatibility.kt
new file mode 100644
index 000000000..798560a76
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/ad/general/annotation/HideAdsCompatibility.kt
@@ -0,0 +1,9 @@
+package app.revanced.patches.youtube.ad.general.annotation
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
+@Target(AnnotationTarget.CLASS)
+internal annotation class HideAdsCompatibility
+
diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/fingerprints/ReelConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/fingerprints/ReelConstructorFingerprint.kt
deleted file mode 100644
index b6140dcc3..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/fingerprints/ReelConstructorFingerprint.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package app.revanced.patches.youtube.ad.general.bytecode.fingerprints
-
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import app.revanced.patches.youtube.ad.general.resource.patch.GeneralAdsResourcePatch
-import org.jf.dexlib2.Opcode
-import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
-
-object ReelConstructorFingerprint : MethodFingerprint(
- opcodes = listOf(
- Opcode.INVOKE_VIRTUAL
- ),
- customFingerprint = { method ->
- method.implementation?.instructions?.any {
- it.opcode == Opcode.CONST && (it as WideLiteralInstruction).wideLiteral == GeneralAdsResourcePatch.reelMultipleItemShelfId
- } ?: false
- }
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/GeneralAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/HideAdsPatch.kt
similarity index 55%
rename from src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/GeneralAdsPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/HideAdsPatch.kt
index 9bcc728a4..4d907a659 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/GeneralAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/HideAdsPatch.kt
@@ -1,47 +1,32 @@
package app.revanced.patches.youtube.ad.general.bytecode.patch
import app.revanced.extensions.findMutableMethodOf
+import app.revanced.extensions.injectHideViewCall
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.addInstruction
-import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
-import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
-import app.revanced.patches.youtube.ad.general.annotation.GeneralAdsCompatibility
-import app.revanced.patches.youtube.ad.general.bytecode.fingerprints.ReelConstructorFingerprint
-import app.revanced.patches.youtube.ad.general.resource.patch.GeneralAdsResourcePatch
-import app.revanced.patches.youtube.misc.fix.backtoexitgesture.patch.FixBackToExitGesturePatch
import app.revanced.patches.shared.misc.fix.verticalscroll.patch.VerticalScrollPatch
-import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
+import app.revanced.patches.youtube.ad.general.annotation.HideAdsCompatibility
+import app.revanced.patches.youtube.ad.general.resource.patch.HideAdsResourcePatch
+import app.revanced.patches.youtube.misc.fix.backtoexitgesture.patch.FixBackToExitGesturePatch
import org.jf.dexlib2.iface.instruction.formats.Instruction31i
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
@Patch
-@DependsOn([GeneralAdsResourcePatch::class, VerticalScrollPatch::class, FixBackToExitGesturePatch::class])
-@Name("general-ads")
+@DependsOn([HideAdsResourcePatch::class, VerticalScrollPatch::class, FixBackToExitGesturePatch::class])
+@Name("hide-ads")
@Description("Removes general ads.")
-@GeneralAdsCompatibility
+@HideAdsCompatibility
@Version("0.0.1")
-class GeneralAdsPatch : BytecodePatch(
- listOf(ReelConstructorFingerprint)
-) {
+class HideAdsPatch : BytecodePatch() {
override fun execute(context: BytecodeContext): PatchResult {
- fun String.buildHideCall(viewRegister: Int) = "invoke-static { v$viewRegister }, " +
- "Lapp/revanced/integrations/patches/GeneralAdsPatch;" +
- "->" +
- "$this(Landroid/view/View;)V"
-
- fun MutableMethod.injectHideCall(insertIndex: Int, viewRegister: Int, method: String) =
- this.addInstruction(insertIndex, method.buildHideCall(viewRegister))
-
context.classes.forEach { classDef ->
classDef.methods.forEach { method ->
with(method.implementation) {
@@ -49,7 +34,7 @@ class GeneralAdsPatch : BytecodePatch(
if (instruction.opcode != org.jf.dexlib2.Opcode.CONST)
return@forEachIndexed
// Instruction to store the id adAttribution into a register
- if ((instruction as Instruction31i).wideLiteral != GeneralAdsResourcePatch.adAttributionId)
+ if ((instruction as Instruction31i).wideLiteral != HideAdsResourcePatch.adAttributionId)
return@forEachIndexed
val insertIndex = index + 1
@@ -64,29 +49,18 @@ class GeneralAdsPatch : BytecodePatch(
context.proxy(classDef)
.mutableClass
.findMutableMethodOf(method)
- .injectHideCall(insertIndex, viewRegister, "hideAdAttributionView")
+ .injectHideViewCall(
+ insertIndex,
+ viewRegister,
+ "Lapp/revanced/integrations/patches/components/AdsFilter;",
+ "hideAdAttributionView"
+ )
}
}
}
}
}
- with(
- ReelConstructorFingerprint.result
- ?: return PatchResultError("Could not resolve fingerprint")
- ) {
- // iput-object v$viewRegister, ...
- val insertIndex = this.scanResult.patternScanResult!!.startIndex + 2
-
- with(this.mutableMethod) {
- val viewRegister = (instruction(insertIndex) as TwoRegisterInstruction).registerA
-
- injectHideCall(insertIndex, viewRegister, "hideReelView")
- }
-
- }
-
return PatchResultSuccess()
}
-
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/general/resource/patch/GeneralAdsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/general/resource/patch/GeneralAdsResourcePatch.kt
deleted file mode 100644
index 4bcaecc3d..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/ad/general/resource/patch/GeneralAdsResourcePatch.kt
+++ /dev/null
@@ -1,303 +0,0 @@
-package app.revanced.patches.youtube.ad.general.resource.patch
-
-import app.revanced.patcher.annotation.Version
-import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.PatchResult
-import app.revanced.patcher.patch.PatchResultSuccess
-import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
-import app.revanced.patches.shared.settings.preference.impl.*
-import app.revanced.patches.youtube.ad.general.annotation.GeneralAdsCompatibility
-import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch.PreferenceScreen
-
-@DependsOn(
- dependencies = [
- LithoFilterPatch::class,
- SettingsPatch::class,
- ResourceMappingPatch::class
- ]
-)
-@GeneralAdsCompatibility
-@Version("0.0.1")
-class GeneralAdsResourcePatch : ResourcePatch {
- internal companion object {
- var adAttributionId: Long = -1
- var reelMultipleItemShelfId: Long = -1
- }
-
- override fun execute(context: ResourceContext): PatchResult {
- PreferenceScreen.LAYOUT.addPreferences(
- SwitchPreference(
- "revanced_adremover_separator",
- StringResource("revanced_adremover_separator_title", "Hide gray separator"),
- true,
- StringResource("revanced_adremover_separator_summary_on", "Gray separators are hidden"),
- StringResource("revanced_adremover_separator_summary_off", "Gray separators are shown")
- ),
- SwitchPreference(
- "revanced_adremover_hide_channel_guidelines",
- StringResource("revanced_adremover_hide_channel_guidelines_enabled_title", "Hide channel guidelines"),
- true,
- StringResource(
- "revanced_adremover_hide_channel_guidelines_enabled_summary_on",
- "Channel guidelines are hidden"
- ),
- StringResource(
- "revanced_adremover_hide_channel_guidelines_enabled_summary_off",
- "Channel guidelines are shown"
- )
- ),
- SwitchPreference(
- "revanced_adremover_chapter_teaser",
- StringResource(
- "revanced_adremover_chapter_teaser_enabled_title",
- "Hide chapter teaser under videos"
- ),
- true,
- StringResource(
- "revanced_adremover_chapter_teaser_enabled_summary_on",
- "Chapter teasers are hidden"
- ),
- StringResource(
- "revanced_adremover_chapter_teaser_enabled_summary_off",
- "Chapter teasers are shown"
- )
- ),
- SwitchPreference(
- "revanced_adremover_merchandise",
- StringResource("revanced_adremover_merchandise_enabled_title", "Hide merchandise banners"),
- true,
- StringResource("revanced_adremover_merchandise_enabled_summary_on", "Merchandise banners are hidden"),
- StringResource("revanced_adremover_merchandise_enabled_summary_off", "Merchandise banners are shown")
- ),
- SwitchPreference(
- "revanced_adremover_community_posts_removal",
- StringResource("revanced_adremover_community_posts_enabled_title", "Hide community posts"),
- false,
- StringResource("revanced_adremover_community_posts_enabled_summary_on", "Community posts are hidden"),
- StringResource("revanced_adremover_community_posts_enabled_summary_off", "Community posts are shown")
- ),
- SwitchPreference(
- "revanced_adremover_compact_banner_removal",
- StringResource("revanced_adremover_compact_banner_enabled_title", "Hide compact banners"),
- true,
- StringResource("revanced_adremover_compact_banner_enabled_summary_on", "Compact banners are hidden"),
- StringResource("revanced_adremover_compact_banner_enabled_summary_off", "Compact banners are shown")
- ),
- SwitchPreference(
- "revanced_adremover_view_products",
- StringResource("revanced_adremover_view_products_title", "Hide banner to view products"),
- true,
- StringResource("revanced_adremover_view_products_summary_on", "Banner is hidden"),
- StringResource("revanced_adremover_view_products_summary_off", "Banner is shown")
- ),
- SwitchPreference(
- "revanced_adremover_web_search_result",
- StringResource("revanced_adremover_web_search_result_panel_title", "Hide web search results"),
- true,
- StringResource("revanced_adremover_web_search_result_summary_on", "Web search results are hidden"),
- StringResource("revanced_adremover_web_search_result_summary_off", "Web search results are shown")
- ),
- SwitchPreference(
- "revanced_adremover_movie",
- StringResource("revanced_adremover_movie_enabled_title", "Hide movies section"),
- true,
- StringResource("revanced_adremover_movie_enabled_summary_on", "Movies section is hidden"),
- StringResource("revanced_adremover_movie_enabled_summary_off", "Movies section is shown")
- ),
- SwitchPreference(
- "revanced_adremover_feed_survey",
- StringResource("revanced_adremover_feed_survey_enabled_title", "Hide feed surveys"),
- true,
- StringResource("revanced_adremover_feed_survey_enabled_summary_on", "Feed surveys are hidden"),
- StringResource("revanced_adremover_feed_survey_enabled_summary_off", "Feed surveys are shown")
- ),
- SwitchPreference(
- "revanced_adremover_shorts",
- StringResource("revanced_adremover_shorts_enabled_title", "Hide shorts"),
- true,
- StringResource("revanced_adremover_shorts_enabled_summary_on", "Shorts are hidden"),
- StringResource("revanced_adremover_shorts_enabled_summary_off", "Shorts are shown")
- ),
- SwitchPreference(
- "revanced_adremover_community_guidelines",
- StringResource("revanced_adremover_community_guidelines_enabled_title", "Hide community guidelines"),
- true,
- StringResource(
- "revanced_adremover_community_guidelines_enabled_summary_on",
- "Community guidelines are hidden"
- ),
- StringResource(
- "revanced_adremover_community_guidelines_enabled_summary_off",
- "Community guidelines are shown"
- )
- ),
- SwitchPreference(
- "revanced_adremover_subscribers_community_guidelines_removal",
- StringResource(
- "revanced_adremover_subscribers_community_guidelines_enabled_title",
- "Hide subscribers community guidelines"
- ),
- true,
- StringResource(
- "revanced_adremover_subscribers_community_guidelines_enabled_summary_on",
- "Subscribers community guidelines are hidden"
- ),
- StringResource(
- "revanced_adremover_subscribers_community_guidelines_enabled_summary_off",
- "Subscribers community guidelines are shown"
- )
- ),
- SwitchPreference(
- "revanced_adremover_channel_member_shelf_removal",
- StringResource("revanced_adremover_channel_member_shelf_enabled_title", "Hide channel member shelf"),
- true,
- StringResource(
- "revanced_adremover_channel_member_shelf_enabled_summary_on",
- "Channel member shelf is hidden"
- ),
- StringResource(
- "revanced_adremover_channel_member_shelf_enabled_summary_off",
- "Channel member shelf is shown"
- )
- ),
- SwitchPreference(
- "revanced_adremover_emergency_box_removal",
- StringResource("revanced_adremover_emergency_box_enabled_title", "Hide emergency boxes"),
- true,
- StringResource("revanced_adremover_emergency_box_enabled_summary_on", "Emergency boxes are hidden"),
- StringResource("revanced_adremover_emergency_box_enabled_summary_off", "Emergency boxes are shown")
- ),
- SwitchPreference(
- "revanced_adremover_info_panel",
- StringResource("revanced_adremover_info_panel_enabled_title", "Hide info panels"),
- true,
- StringResource("revanced_adremover_info_panel_enabled_summary_on", "Info panels are hidden"),
- StringResource("revanced_adremover_info_panel_enabled_summary_off", "Info panels are shown")
- ),
- SwitchPreference(
- "revanced_adremover_medical_panel",
- StringResource("revanced_adremover_medical_panel_enabled_title", "Hide medical panels"),
- true,
- StringResource("revanced_adremover_medical_panel_enabled_summary_on", "Medical panels are hidden"),
- StringResource("revanced_adremover_medical_panel_enabled_summary_off", "Medical panels are shown")
- ),
- SwitchPreference(
- "revanced_hide_channel_bar",
- StringResource("revanced_hide_channel_bar_title", "Hide channel bar"),
- false,
- StringResource("revanced_hide_channel_bar_summary_on", "Channel bar is hidden"),
- StringResource("revanced_hide_channel_bar_summary_off", "Channel bar is shown")
- ),
- SwitchPreference(
- "revanced_hide_quick_actions",
- StringResource("revanced_hide_quick_actions_title", "Hide quick actions in fullscreen"),
- false,
- StringResource("revanced_hide_quick_actions_summary_on", "Quick actions are hidden"),
- StringResource("revanced_hide_quick_actions_summary_off", "Quick actions are shown")
- ),
- SwitchPreference(
- "revanced_hide_related_videos",
- StringResource("revanced_hide_related_videos_title", "Hide related videos in quick actions"),
- false,
- StringResource("revanced_hide_related_videos_summary_on", "Related videos are hidden"),
- StringResource("revanced_hide_related_videos_summary_off", "Related videos are shown")
- ),
- SwitchPreference(
- "revanced_hide_image_shelf",
- StringResource("revanced_hide_image_shelf", "Hide image shelf in search results"),
- true,
- StringResource("revanced_hide_image_shelf_summary_on", "Image shelf is hidden"),
- StringResource("revanced_hide_image_shelf_summary_off", "Image shelf is shown")
- ),
- SwitchPreference(
- "revanced_hide_audio_track_button",
- StringResource("revanced_hide_audio_track_button_title", "Hide audio track button"),
- false,
- StringResource("revanced_hide_audio_track_button_on", "Audio track button is hidden"),
- StringResource("revanced_hide_audio_track_button_off", "Audio track button is shown")
- )
- )
-
- PreferenceScreen.ADS.addPreferences(
- SwitchPreference(
- "revanced_adremover_ad_removal",
- StringResource("revanced_adremover_ad_removal_enabled_title", "Hide general ads"),
- true,
- StringResource("revanced_adremover_ad_removal_enabled_summary_on", "General ads are hidden"),
- StringResource("revanced_adremover_ad_removal_enabled_summary_off", "General ads are shown")
- ),
- SwitchPreference(
- "revanced_adremover_buttoned",
- StringResource("revanced_adremover_buttoned_enabled_title", "Hide buttoned ad"),
- true,
- StringResource("revanced_adremover_buttoned_enabled_summary_on", "Buttoned ads are hidden"),
- StringResource("revanced_adremover_buttoned_enabled_summary_off", "Buttoned ads are shown")
- ),
- SwitchPreference(
- "revanced_adremover_paid_content",
- StringResource("revanced_adremover_paid_content_enabled_title", "Hide paid content"),
- true,
- StringResource("revanced_adremover_paid_content_enabled_summary_on", "Paid content is hidden"),
- StringResource("revanced_adremover_paid_content_enabled_summary_off", "Paid content is shown")
- ),
- SwitchPreference(
- "revanced_adremover_hide_latest_posts",
- StringResource("revanced_adremover_hide_latest_posts_enabled_title", "Hide latest posts"),
- true,
- StringResource("revanced_adremover_hide_latest_posts_enabled_summary_on", "Latest posts are hidden"),
- StringResource("revanced_adremover_hide_latest_posts_enabled_summary_off", "Latest posts are shown")
- ),
- SwitchPreference(
- "revanced_adremover_self_sponsor",
- StringResource("revanced_adremover_self_sponsor_enabled_title", "Hide self sponsored cards"),
- true,
- StringResource("revanced_adremover_self_sponsor_enabled_summary_on", "Self sponsored cards are hidden"),
- StringResource("revanced_adremover_self_sponsor_enabled_summary_off", "Self sponsored cards are shown")
- ),
- PreferenceScreen(
- "revanced_adremover_custom",
- StringResource("revanced_adremover_custom_title", "Custom filter"),
- listOf(
- SwitchPreference(
- "revanced_adremover_custom_enabled",
- StringResource(
- "revanced_adremover_custom_enabled_title",
- "Enable custom filter"
- ),
- false,
- StringResource(
- "revanced_adremover_custom_enabled_summary_on",
- "Custom filter is enabled"
- ),
- StringResource(
- "revanced_adremover_custom_enabled_summary_off",
- "Custom filter is disabled"
- )
- ),
- // TODO: This should be a dynamic ListPreference, which does not exist yet
- TextPreference(
- "revanced_adremover_custom_strings",
- StringResource("revanced_adremover_custom_strings_title", "Custom filter"),
- InputType.STRING,
- "",
- StringResource(
- "revanced_adremover_custom_strings_summary",
- "Filter components by their name separated by a comma"
- )
- )
- )
- )
- )
-
- fun String.getId() = ResourceMappingPatch.resourceMappings.single { it.name == this }.id
-
- adAttributionId = "ad_attribution".getId()
- reelMultipleItemShelfId = "reel_multiple_items_shelf".getId()
-
- return PatchResultSuccess()
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/general/resource/patch/HideAdsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/general/resource/patch/HideAdsResourcePatch.kt
new file mode 100644
index 000000000..4491d4326
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/ad/general/resource/patch/HideAdsResourcePatch.kt
@@ -0,0 +1,264 @@
+package app.revanced.patches.youtube.ad.general.resource.patch
+
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.ResourceContext
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.ResourcePatch
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patches.shared.settings.preference.impl.*
+import app.revanced.patches.youtube.ad.general.annotation.HideAdsCompatibility
+import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
+import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch.PreferenceScreen
+
+@DependsOn(
+ dependencies = [
+ LithoFilterPatch::class,
+ SettingsPatch::class,
+ ResourceMappingPatch::class
+ ]
+)
+@HideAdsCompatibility
+@Version("0.0.1")
+class HideAdsResourcePatch : ResourcePatch {
+
+ override fun execute(context: ResourceContext): PatchResult {
+ PreferenceScreen.LAYOUT.addPreferences(
+ SwitchPreference(
+ "revanced_hide_gray_separator",
+ StringResource("revanced_hide_gray_separator_title", "Hide gray separator"),
+ StringResource("revanced_hide_gray_separator_summary_on", "Gray separators are hidden"),
+ StringResource("revanced_hide_gray_separator_summary_off", "Gray separators are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_channel_guidelines",
+ StringResource("revanced_hide_channel_guidelines_title", "Hide channel guidelines"),
+ StringResource(
+ "revanced_hide_channel_guidelines_summary_on",
+ "Channel guidelines are hidden"
+ ),
+ StringResource(
+ "revanced_hide_channel_guidelines_summary_off",
+ "Channel guidelines are shown"
+ )
+ ),
+ SwitchPreference(
+ "revanced_hide_chapter_teaser",
+ StringResource(
+ "revanced_hide_chapter_teaser_title",
+ "Hide chapter teaser under videos"
+ ),
+ StringResource(
+ "revanced_hide_chapter_teaser_summary_on",
+ "Chapter teasers are hidden"
+ ),
+ StringResource(
+ "revanced_hide_chapter_teaser_summary_off",
+ "Chapter teasers are shown"
+ )
+ ),
+ SwitchPreference(
+ "revanced_hide_merchandise_banners",
+ StringResource("revanced_hide_merchandise_banners_title", "Hide merchandise banners"),
+ StringResource("revanced_hide_merchandise_banners_summary_on", "Merchandise banners are hidden"),
+ StringResource("revanced_hide_merchandise_banners_summary_off", "Merchandise banners are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_community_posts",
+ StringResource("revanced_hide_community_posts_title", "Hide community posts"),
+ StringResource("revanced_hide_community_posts_summary_on", "Community posts are hidden"),
+ StringResource("revanced_hide_community_posts_summary_off", "Community posts are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_compact_banner",
+ StringResource("revanced_hide_compact_banner_title", "Hide compact banners"),
+ StringResource("revanced_hide_compact_banner_summary_on", "Compact banners are hidden"),
+ StringResource("revanced_hide_compact_banner_summary_off", "Compact banners are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_products_banner",
+ StringResource("revanced_hide_products_banner_title", "Hide banner to view products"),
+ StringResource("revanced_hide_products_banner_summary_on", "Banner is hidden"),
+ StringResource("revanced_hide_products_banner_summary_off", "Banner is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_web_search_results",
+ StringResource("revanced_hide_web_search_results_title", "Hide web search results"),
+ StringResource("revanced_hide_web_search_results_summary_on", "Web search results are hidden"),
+ StringResource("revanced_hide_web_search_results_summary_off", "Web search results are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_movies_section",
+ StringResource("revanced_hide_movies_section_title", "Hide movies section"),
+ StringResource("revanced_hide_movies_section_summary_on", "Movies section is hidden"),
+ StringResource("revanced_hide_movies_section_summary_off", "Movies section is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_feed_survey",
+ StringResource("revanced_hide_feed_survey_title", "Hide feed surveys"),
+ StringResource("revanced_hide_feed_survey_summary_on", "Feed surveys are hidden"),
+ StringResource("revanced_hide_feed_survey_summary_off", "Feed surveys are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_community_guidelines",
+ StringResource("revanced_hide_community_guidelines_title", "Hide community guidelines"),
+ StringResource(
+ "revanced_hide_community_guidelines_summary_on",
+ "Community guidelines are hidden"
+ ),
+ StringResource(
+ "revanced_hide_community_guidelines_summary_off",
+ "Community guidelines are shown"
+ )
+ ),
+ SwitchPreference(
+ "revanced_hide_subscribers_community_guidelines",
+ StringResource(
+ "revanced_hide_subscribers_community_guidelines_title",
+ "Hide subscribers community guidelines"
+ ),
+ StringResource(
+ "revanced_hide_subscribers_community_guidelines_summary_on",
+ "Subscribers community guidelines are hidden"
+ ),
+ StringResource(
+ "revanced_hide_subscribers_community_guidelines_summary_off",
+ "Subscribers community guidelines are shown"
+ )
+ ),
+ SwitchPreference(
+ "revanced_hide_channel_member_shelf",
+ StringResource("revanced_hide_channel_member_shelf_title", "Hide channel member shelf"),
+ StringResource(
+ "revanced_hide_channel_member_shelf_summary_on",
+ "Channel member shelf is hidden"
+ ),
+ StringResource(
+ "revanced_hide_channel_member_shelf_summary_off",
+ "Channel member shelf is shown"
+ )
+ ),
+ SwitchPreference(
+ "revanced_hide_emergency_box",
+ StringResource("revanced_hide_emergency_box_title", "Hide emergency boxes"),
+ StringResource("revanced_hide_emergency_box_summary_on", "Emergency boxes are hidden"),
+ StringResource("revanced_hide_emergency_box_summary_off", "Emergency boxes are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_info_panels",
+ StringResource("revanced_hide_info_panels_title", "Hide info panels"),
+ StringResource("revanced_hide_info_panels_summary_on", "Info panels are hidden"),
+ StringResource("revanced_hide_info_panels_summary_off", "Info panels are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_medical_panels",
+ StringResource("revanced_hide_medical_panels_title", "Hide medical panels"),
+ StringResource("revanced_hide_medical_panels_summary_on", "Medical panels are hidden"),
+ StringResource("revanced_hide_medical_panels_summary_off", "Medical panels are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_channel_bar",
+ StringResource("revanced_hide_channel_bar_title", "Hide channel bar"),
+ StringResource("revanced_hide_channel_bar_summary_on", "Channel bar is hidden"),
+ StringResource("revanced_hide_channel_bar_summary_off", "Channel bar is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_quick_actions",
+ StringResource("revanced_hide_quick_actions_title", "Hide quick actions in fullscreen"),
+ StringResource("revanced_hide_quick_actions_summary_on", "Quick actions are hidden"),
+ StringResource("revanced_hide_quick_actions_summary_off", "Quick actions are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_related_videos",
+ StringResource("revanced_hide_related_videos_title", "Hide related videos in quick actions"),
+ StringResource("revanced_hide_related_videos_summary_on", "Related videos are hidden"),
+ StringResource("revanced_hide_related_videos_summary_off", "Related videos are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_image_shelf",
+ StringResource("revanced_hide_image_shelf", "Hide image shelf in search results"),
+ StringResource("revanced_hide_image_shelf_summary_on", "Image shelf is hidden"),
+ StringResource("revanced_hide_image_shelf_summary_off", "Image shelf is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_audio_track_button",
+ StringResource("revanced_hide_audio_track_button_title", "Hide audio track button"),
+ StringResource("revanced_hide_audio_track_button_on", "Audio track button is hidden"),
+ StringResource("revanced_hide_audio_track_button_off", "Audio track button is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_latest_posts_ads",
+ StringResource("revanced_hide_latest_posts_ads_title", "Hide latest posts"),
+ StringResource("revanced_hide_latest_posts_ads_summary_on", "Latest posts are hidden"),
+ StringResource("revanced_hide_latest_posts_ads_summary_off", "Latest posts are shown")
+ ),
+ )
+
+ PreferenceScreen.ADS.addPreferences(
+ SwitchPreference(
+ "revanced_hide_general_ads",
+ StringResource("revanced_hide_general_ads_title", "Hide general ads"),
+ StringResource("revanced_hide_general_ads_summary_on", "General ads are hidden"),
+ StringResource("revanced_hide_general_ads_summary_off", "General ads are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_buttoned_ads",
+ StringResource("revanced_hide_buttoned_ads_title", "Hide buttoned ad"),
+ StringResource("revanced_hide_buttoned_ads_summary_on", "Buttoned ads are hidden"),
+ StringResource("revanced_hide_buttoned_ads_summary_off", "Buttoned ads are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_paid_content_ads",
+ StringResource("revanced_hide_paid_content_ads_title", "Hide paid content"),
+ StringResource("revanced_hide_paid_content_ads_summary_on", "Paid content is hidden"),
+ StringResource("revanced_hide_paid_content_ads_summary_off", "Paid content is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_self_sponsor_ads",
+ StringResource("revanced_hide_self_sponsor_ads_title", "Hide self sponsored cards"),
+ StringResource("revanced_hide_self_sponsor_ads_summary_on", "Self sponsored cards are hidden"),
+ StringResource("revanced_hide_self_sponsor_ads_summary_off", "Self sponsored cards are shown")
+ ),
+ PreferenceScreen(
+ "revanced_custom_filter_preference_screen",
+ StringResource("revanced_custom_filter_preference_screen_title", "Custom filter"),
+ listOf(
+ SwitchPreference(
+ "revanced_custom_filter",
+ StringResource(
+ "revanced_custom_filter_title",
+ "Enable custom filter"
+ ),
+ StringResource(
+ "revanced_custom_filter_summary_on",
+ "Custom filter is enabled"
+ ),
+ StringResource(
+ "revanced_custom_filter_summary_off",
+ "Custom filter is disabled"
+ )
+ ),
+ // TODO: This should be a dynamic ListPreference, which does not exist yet
+ TextPreference(
+ "revanced_custom_filter_strings",
+ StringResource("revanced_custom_filter_strings_title", "Custom filter"),
+ StringResource(
+ "revanced_custom_filter_strings_summary",
+ "Filter components by their name separated by a comma"
+ )
+ )
+ )
+ )
+ )
+
+ adAttributionId = ResourceMappingPatch.resourceMappings.single { it.name == "ad_attribution" }.id
+
+ return PatchResultSuccess()
+ }
+
+ internal companion object {
+ var adAttributionId: Long = -1
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/video/annotations/VideoAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/video/annotations/VideoAdsCompatibility.kt
index a6e9279e8..6713227a1 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/ad/video/annotations/VideoAdsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/ad/video/annotations/VideoAdsCompatibility.kt
@@ -3,23 +3,7 @@ package app.revanced.patches.youtube.ad.video.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class VideoAdsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/video/patch/VideoAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/video/patch/VideoAdsPatch.kt
index 10e14d39d..000b4b54b 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/ad/video/patch/VideoAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/ad/video/patch/VideoAdsPatch.kt
@@ -33,11 +33,10 @@ class VideoAdsPatch : BytecodePatch(
override fun execute(context: BytecodeContext): PatchResult {
SettingsPatch.PreferenceScreen.ADS.addPreferences(
SwitchPreference(
- "revanced_video_ads_removal",
- StringResource("revanced_video_ads_removal_title", "Hide video ads"),
- true,
- StringResource("revanced_video_ads_removal_summary_on", "Video ads are hidden"),
- StringResource("revanced_video_ads_removal_summary_off", "Video ads are shown")
+ "revanced_hide_video_ads",
+ StringResource("revanced_hide_video_ads_title", "Hide video ads"),
+ StringResource("revanced_hide_video_ads_summary_on", "Video ads are hidden"),
+ StringResource("revanced_hide_video_ads_summary_off", "Video ads are shown")
)
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/annotation/CopyVideoUrlCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/annotation/CopyVideoUrlCompatibility.kt
index df42c40f2..fc46729a4 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/annotation/CopyVideoUrlCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/annotation/CopyVideoUrlCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.interaction.copyvideourl.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class CopyVideoUrlCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/bytecode/patch/CopyVideoUrlBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/bytecode/patch/CopyVideoUrlBytecodePatch.kt
index c015612a4..46823e409 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/bytecode/patch/CopyVideoUrlBytecodePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/bytecode/patch/CopyVideoUrlBytecodePatch.kt
@@ -12,7 +12,7 @@ import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.youtube.interaction.copyvideourl.annotation.CopyVideoUrlCompatibility
import app.revanced.patches.youtube.interaction.copyvideourl.resource.patch.CopyVideoUrlResourcePatch
import app.revanced.patches.youtube.misc.playercontrols.bytecode.patch.PlayerControlsBytecodePatch
-import app.revanced.patches.youtube.misc.video.information.patch.VideoInformationPatch
+import app.revanced.patches.youtube.video.information.patch.VideoInformationPatch
@Patch
@Name("copy-video-url")
@@ -26,8 +26,7 @@ import app.revanced.patches.youtube.misc.video.information.patch.VideoInformatio
@Version("0.0.1")
class CopyVideoUrlBytecodePatch : BytecodePatch() {
private companion object {
- const val INTEGRATIONS_PACKAGE = "Lapp/revanced/integrations"
- const val INTEGRATIONS_PLAYER_PACKAGE = "$INTEGRATIONS_PACKAGE/videoplayer"
+ const val INTEGRATIONS_PLAYER_PACKAGE = "Lapp/revanced/integrations/videoplayer"
val BUTTONS_DESCRIPTORS = listOf(
"$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlButton;",
"$INTEGRATIONS_PLAYER_PACKAGE/CopyVideoUrlTimestampButton;"
@@ -38,10 +37,8 @@ class CopyVideoUrlBytecodePatch : BytecodePatch() {
// Initialize buttons and inject visibility control
BUTTONS_DESCRIPTORS.forEach { descriptor ->
- val initializeButtonDescriptor = "$descriptor->initializeButton(Ljava/lang/Object;)V"
- val visibilityDescriptor = "$descriptor->changeVisibility(Z)V"
- PlayerControlsBytecodePatch.initializeControl(initializeButtonDescriptor)
- PlayerControlsBytecodePatch.injectVisibilityCheckCall(visibilityDescriptor)
+ PlayerControlsBytecodePatch.initializeControl("$descriptor->initializeButton(Landroid/view/View;)V")
+ PlayerControlsBytecodePatch.injectVisibilityCheckCall("$descriptor->changeVisibility(Z)V")
}
return PatchResultSuccess()
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/resource/patch/CopyVideoUrlResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/resource/patch/CopyVideoUrlResourcePatch.kt
index 6e60282cd..3d0124fd4 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/resource/patch/CopyVideoUrlResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/resource/patch/CopyVideoUrlResourcePatch.kt
@@ -1,6 +1,5 @@
package app.revanced.patches.youtube.interaction.copyvideourl.resource.patch
-import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext
@@ -11,40 +10,36 @@ import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.interaction.copyvideourl.annotation.CopyVideoUrlCompatibility
import app.revanced.patches.youtube.misc.playercontrols.resource.patch.BottomControlsResourcePatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources
+import app.revanced.util.resources.ResourceUtils.mergeStrings
@Name("copy-video-url-resource")
-@Description("Makes necessary changes to resources for copy video link buttons.")
@DependsOn([BottomControlsResourcePatch::class, SettingsPatch::class])
-@CopyVideoUrlCompatibility
@Version("0.0.1")
class CopyVideoUrlResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
PreferenceScreen(
- "revanced_copy_video_url",
- StringResource("revanced_copy_video_url_title", "Copy video URL settings"),
+ "revanced_copy_video_url_preference_screen",
+ StringResource("revanced_copy_video_url_preference_screen_title", "Copy video URL settings"),
listOf(
SwitchPreference(
- "revanced_copy_video_url_enabled",
- StringResource("revanced_copy_video_url_enabled_title", "Show copy video URL button"),
- true,
- StringResource("revanced_copy_video_url_enabled_summary_on", "Button is shown, click to copy video URL without timestamp"),
- StringResource("revanced_copy_video_url_enabled_summary_off", "Button is not shown")
+ "revanced_copy_video_url",
+ StringResource("revanced_copy_video_url_title", "Show copy video URL button"),
+ StringResource("revanced_copy_video_url_summary_on", "Button is shown. Tap to copy video URL. Tap and hold to copy video URL with timestamp"),
+ StringResource("revanced_copy_video_url_summary_off", "Button is not shown")
),
SwitchPreference(
- "revanced_copy_video_url_timestamp_enabled",
- StringResource("revanced_copy_video_url_timestamp_enabled_title", "Show copy timestamp URL button"),
- true,
- StringResource("revanced_copy_video_url_timestamp_enabled_summary_on", "Button is shown, click to copy video URL with timestamp"),
- StringResource("revanced_copy_video_url_timestamp_enabled_summary_off", "Button is not shown")
+ "revanced_copy_video_url_timestamp",
+ StringResource("revanced_copy_video_url_timestamp_title", "Show copy timestamp URL button"),
+ StringResource("revanced_copy_video_url_timestamp_summary_on", "Button is shown. Tap to copy video URL with timestamp. Tap and hold to copy video without timestamp"),
+ StringResource("revanced_copy_video_url_timestamp_summary_off", "Button is not shown")
)
),
- StringResource("revanced_copy_video_url_summary", "Settings related to copy URL buttons in video player")
+ StringResource("revanced_copy_video_url_preference_screen_summary", "Settings related to copy URL buttons in video player")
)
)
@@ -54,6 +49,9 @@ class CopyVideoUrlResourcePatch : ResourcePatch {
"revanced_yt_copy_timestamp.xml"
))
+ // merge strings
+ context.mergeStrings("copyvideourl/host/values/strings.xml")
+
BottomControlsResourcePatch.addControls("copyvideourl/host/layout/${BottomControlsResourcePatch.TARGET_RESOURCE_NAME}")
return PatchResultSuccess()
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/annotation/DownloadsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/annotation/DownloadsCompatibility.kt
index 9f84d2ab6..5e8525309 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/annotation/DownloadsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/annotation/DownloadsCompatibility.kt
@@ -3,23 +3,7 @@ package app.revanced.patches.youtube.interaction.downloads.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class DownloadsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/bytecode/patch/DownloadsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/bytecode/patch/DownloadsBytecodePatch.kt
index 244dbeadf..d296b396f 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/bytecode/patch/DownloadsBytecodePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/bytecode/patch/DownloadsBytecodePatch.kt
@@ -12,32 +12,33 @@ import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.youtube.interaction.downloads.annotation.DownloadsCompatibility
import app.revanced.patches.youtube.interaction.downloads.resource.patch.DownloadsResourcePatch
import app.revanced.patches.youtube.misc.playercontrols.bytecode.patch.PlayerControlsBytecodePatch
-import app.revanced.patches.youtube.misc.video.information.patch.VideoInformationPatch
+import app.revanced.patches.youtube.video.information.patch.VideoInformationPatch
@Patch
@Name("downloads")
@DependsOn([DownloadsResourcePatch::class, PlayerControlsBytecodePatch::class, VideoInformationPatch::class])
-@Description("Enables downloading music and videos from YouTube.")
+@Description("Adds a download button to the YouTube video player.")
@DownloadsCompatibility
@Version("0.0.1")
class DownloadsBytecodePatch : BytecodePatch() {
- override fun execute(context: BytecodeContext): PatchResult {
- val integrationsPackage = "app/revanced/integrations"
- val classDescriptor = "L$integrationsPackage/videoplayer/DownloadButton;"
+ private companion object {
+ const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/videoplayer/DownloadButton;"
+ }
+ override fun execute(context: BytecodeContext): PatchResult {
/*
initialize the control
*/
- val initializeDownloadsDescriptor = "$classDescriptor->initializeButton(Ljava/lang/Object;)V"
- PlayerControlsBytecodePatch.initializeControl(initializeDownloadsDescriptor)
+ PlayerControlsBytecodePatch.initializeControl(
+ "$BUTTON_DESCRIPTOR->initializeButton(Landroid/view/View;)V")
/*
add code to change the visibility of the control
*/
- val changeVisibilityDescriptor = "$classDescriptor->changeVisibility(Z)V"
- PlayerControlsBytecodePatch.injectVisibilityCheckCall(changeVisibilityDescriptor)
+ PlayerControlsBytecodePatch.injectVisibilityCheckCall(
+ "$BUTTON_DESCRIPTOR->changeVisibility(Z)V")
return PatchResultSuccess()
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/resource/patch/DownloadsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/resource/patch/DownloadsResourcePatch.kt
index f628f4d0c..4ab4a883c 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/resource/patch/DownloadsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/resource/patch/DownloadsResourcePatch.kt
@@ -1,6 +1,5 @@
package app.revanced.patches.youtube.interaction.downloads.resource.patch
-import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext
@@ -9,7 +8,6 @@ import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.settings.preference.impl.*
-import app.revanced.patches.youtube.interaction.downloads.annotation.DownloadsCompatibility
import app.revanced.patches.youtube.misc.playercontrols.resource.patch.BottomControlsResourcePatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.util.resources.ResourceUtils
@@ -18,32 +16,28 @@ import app.revanced.util.resources.ResourceUtils.mergeStrings
@Name("downloads-resource-patch")
@DependsOn([BottomControlsResourcePatch::class, SettingsPatch::class])
-@Description("Makes necessary changes to resources for the download button.")
-@DownloadsCompatibility
@Version("0.0.1")
class DownloadsResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
PreferenceScreen(
- "revanced_downloads",
- StringResource("revanced_downloads_title", "Download settings"),
+ "revanced_external_downloader_preference_screen",
+ StringResource("revanced_external_downloader_preference_screen_title", "Download settings"),
listOf(
SwitchPreference(
- "revanced_downloads_enabled",
- StringResource("revanced_downloads_enabled_title", "Show download button"),
- true,
- StringResource("revanced_downloads_enabled_summary_on", "Download button is shown"),
- StringResource("revanced_downloads_enabled_summary_off", "Download button is not shown")
+ "revanced_external_downloader",
+ StringResource("revanced_external_downloader_title", "Show download button"),
+ StringResource("revanced_external_downloader_summary_on", "Download button is shown"),
+ StringResource("revanced_external_downloader_summary_off", "Download button is not shown")
),
TextPreference(
- "revanced_downloads_package_name",
- StringResource("revanced_downloads_package_name_title", "Downloader package name"),
- InputType.STRING,
- "org.schabi.newpipe" /* NewPipe */,
- StringResource("revanced_downloads_package_name_summary", "Package name of the downloader app such as NewPipe\\'s or PowerTube\\'s")
+ "revanced_external_downloader_name",
+ StringResource("revanced_external_downloader_name_title", "Downloader package name"),
+ StringResource("revanced_external_downloader_name_summary", "Package name of the downloader app such as NewPipe\\'s or PowerTube\\'s"),
+ InputType.TEXT
)
),
- StringResource("revanced_downloads_summary", "Settings related to downloads")
+ StringResource("revanced_external_downloader_preference_screen_summary", "Settings related to downloads")
)
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/annotation/SeekbarTappingCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/annotation/SeekbarTappingCompatibility.kt
index b0aef8f99..56a7b6893 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/annotation/SeekbarTappingCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/annotation/SeekbarTappingCompatibility.kt
@@ -3,23 +3,7 @@ package app.revanced.patches.youtube.interaction.seekbar.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class SeekbarTappingCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/fingerprints/AccessibilityPlayerProgressTimeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/fingerprints/AccessibilityPlayerProgressTimeFingerprint.kt
new file mode 100644
index 000000000..d6d0653af
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/fingerprints/AccessibilityPlayerProgressTimeFingerprint.kt
@@ -0,0 +1,23 @@
+package app.revanced.patches.youtube.interaction.seekbar.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import app.revanced.patches.youtube.interaction.seekbar.patch.EnableSeekbarTappingResourcePatch
+import org.jf.dexlib2.AccessFlags
+import org.jf.dexlib2.Opcode
+import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
+
+
+object AccessibilityPlayerProgressTimeFingerprint : MethodFingerprint(
+ returnType = "L",
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ customFingerprint = { methodDef, _ ->
+ methodDef.implementation?.instructions?.any { instruction ->
+ if (instruction.opcode != Opcode.CONST) return@any false
+
+ val wideLiteral = (instruction as WideLiteralInstruction).wideLiteral
+
+ EnableSeekbarTappingResourcePatch.accessibilityPlayerProgressTime == wideLiteral
+ } ?: false
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/fingerprints/SeekbarTappingFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/fingerprints/SeekbarTappingFingerprint.kt
index 94d6b2cef..3c8f3ed0b 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/fingerprints/SeekbarTappingFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/fingerprints/SeekbarTappingFingerprint.kt
@@ -1,34 +1,34 @@
package app.revanced.patches.youtube.interaction.seekbar.fingerprints
import app.revanced.patcher.extensions.or
-import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
+import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
-@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
object SeekbarTappingFingerprint : MethodFingerprint(
- "Z", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L"), listOf(
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT_WIDE,
- Opcode.IGET,
- Opcode.IGET_OBJECT,
- Opcode.IGET,
- Opcode.DIV_INT_2ADDR,
- Opcode.ADD_INT,
- Opcode.SUB_INT_2ADDR,
- Opcode.INT_TO_FLOAT,
- Opcode.CMPG_FLOAT,
- Opcode.IF_GTZ,
- Opcode.INT_TO_FLOAT,
- Opcode.CMPG_FLOAT,
- Opcode.IF_GTZ,
- Opcode.CONST_4,
- Opcode.INVOKE_INTERFACE,
- Opcode.NEW_INSTANCE,
- Opcode.INVOKE_DIRECT,
+ returnType = "Z",
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ parameters = listOf("L"),
+ opcodes = listOf(
Opcode.IPUT_OBJECT,
- Opcode.INVOKE_VIRTUAL
- )
+ Opcode.INVOKE_VIRTUAL,
+ // Insert seekbar tapping instructions here.
+ Opcode.RETURN,
+ Opcode.INVOKE_VIRTUAL,
+ ),
+ customFingerprint = custom@{ methodDef, _ ->
+ if (methodDef.name != "onTouchEvent") return@custom false
+
+ methodDef.implementation!!.instructions.any { instruction ->
+ if (instruction.opcode != Opcode.CONST) return@any false
+
+ val literal = (instruction as NarrowLiteralInstruction).narrowLiteral
+
+ // onTouchEvent method contains a CONST instruction
+ // with this literal making it unique with the rest of the properties of this fingerprint.
+ literal == Integer.MAX_VALUE
+ }
+ }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/fingerprints/SeekbarTappingParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/fingerprints/SeekbarTappingParentFingerprint.kt
deleted file mode 100644
index 20f83effb..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/fingerprints/SeekbarTappingParentFingerprint.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-package app.revanced.patches.youtube.interaction.seekbar.fingerprints
-
-import app.revanced.patcher.extensions.or
-import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import org.jf.dexlib2.AccessFlags
-import org.jf.dexlib2.Opcode
-
-
-@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
-object SeekbarTappingParentFingerprint : MethodFingerprint(
- "L", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf(
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.CONST_4,
- Opcode.NEW_ARRAY,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT_WIDE,
- Opcode.INVOKE_STATIC,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.INVOKE_STATIC,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.CONST_4,
- Opcode.APUT_OBJECT,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT_WIDE,
- Opcode.INVOKE_STATIC,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.INVOKE_STATIC,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.CONST_4,
- Opcode.APUT_OBJECT,
- Opcode.CONST,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.RETURN_OBJECT
- )
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingPatch.kt
index fed792408..b9d0dc097 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingPatch.kt
@@ -1,110 +1,95 @@
package app.revanced.patches.youtube.interaction.seekbar.patch
+import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
-import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility
+import app.revanced.patches.youtube.interaction.seekbar.fingerprints.AccessibilityPlayerProgressTimeFingerprint
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.SeekbarTappingFingerprint
-import app.revanced.patches.youtube.interaction.seekbar.fingerprints.SeekbarTappingParentFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-import app.revanced.patches.shared.settings.preference.impl.StringResource
-import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import org.jf.dexlib2.Opcode
-import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
import org.jf.dexlib2.iface.Method
-import org.jf.dexlib2.iface.instruction.formats.Instruction11n
+import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
+@DependsOn([IntegrationsPatch::class, EnableSeekbarTappingResourcePatch::class])
@Name("seekbar-tapping")
@Description("Enables tap-to-seek on the seekbar of the video player.")
@SeekbarTappingCompatibility
@Version("0.0.1")
class EnableSeekbarTappingPatch : BytecodePatch(
- listOf(
- SeekbarTappingParentFingerprint, SeekbarTappingFingerprint
- )
+ listOf(AccessibilityPlayerProgressTimeFingerprint, SeekbarTappingFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
- SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
- SwitchPreference(
- "revanced_enable_tap_seeking",
- StringResource("revanced_seekbar_tapping_enabled_title", "Enable seekbar tapping"),
- true,
- StringResource("revanced_seekbar_tapping_summary_on", "Seekbar tapping is enabled"),
- StringResource("revanced_seekbar_tapping_summary_off", "Seekbar tapping is disabled")
- )
- )
+ // Find the required methods to tap the seekbar.
+ val seekbarTappingMethods =
+ AccessibilityPlayerProgressTimeFingerprint.result?.classDef?.methods?.let { methods ->
+ buildMap {
+ // find the methods which tap the seekbar
+ methods.forEach { method ->
+ if (method.implementation == null) return@forEach
- var result = SeekbarTappingParentFingerprint.result!!
+ val instructions = method.implementation!!.instructions
- val tapSeekMethods = mutableMapOf()
+ // The method has more than 7 instructions.
+ if (instructions.count() < 7) return@forEach
- // find the methods which tap the seekbar
- for (it in result.classDef.methods) {
- if (it.implementation == null) continue
+ // The 7th instruction has the opcode CONST_4.
+ val instruction = instructions.elementAt(6)
+ if (instruction.opcode != Opcode.CONST_4) return@forEach
- val instructions = it.implementation!!.instructions
- // here we make sure we actually find the method because it has more than 7 instructions
- if (instructions.count() < 7) continue
+ // the literal for this instruction has to be either 1 or 2.
+ val literal = (instruction as NarrowLiteralInstruction).narrowLiteral
- // we know that the 7th instruction has the opcode CONST_4
- val instruction = instructions.elementAt(6)
- if (instruction.opcode != Opcode.CONST_4) continue
+ // Based on the literal, determine which method is which.
+ if (literal == 1) this["P"] = method
+ if (literal == 2) this["O"] = method
+ }
+ }
+ }
- // the literal for this instruction has to be either 1 or 2
- val literal = (instruction as Instruction11n).narrowLiteral
+ seekbarTappingMethods ?: return AccessibilityPlayerProgressTimeFingerprint.toErrorResult()
- // method founds
- if (literal == 1) tapSeekMethods["P"] = it
- if (literal == 2) tapSeekMethods["O"] = it
- }
+ SeekbarTappingFingerprint.result?.let {
+ val insertIndex = it.scanResult.patternScanResult!!.endIndex - 1
- // replace map because we don't need the upper one anymore
- result = SeekbarTappingFingerprint.result!!
+ it.mutableMethod.apply {
+ val thisInstanceRegister = instruction(insertIndex - 1).registerC
- val implementation = result.mutableMethod.implementation!!
+ val freeRegister = 0
+ val xAxisRegister = 2
- // if tap-seeking is enabled, do not invoke the two methods below
- val pMethod = tapSeekMethods["P"]!!
- val oMethod = tapSeekMethods["O"]!!
+ val pMethod = seekbarTappingMethods["P"]!!
+ val oMethod = seekbarTappingMethods["O"]!!
- val insertIndex = result.scanResult.patternScanResult!!.endIndex + 1
+ fun Method.toInvokeInstructionString() =
+ "invoke-virtual { v$thisInstanceRegister, v$xAxisRegister }, $definingClass->$name(I)V"
- // get the required register
- val instruction = implementation.instructions[insertIndex - 1]
- if (instruction.opcode != Opcode.INVOKE_VIRTUAL) return PatchResultError("Could not find the correct register")
- val register = (instruction as Instruction35c).registerC
+ addInstructions(
+ insertIndex,
+ """
+ invoke-static { }, Lapp/revanced/integrations/patches/SeekbarTappingPatch;->seekbarTappingEnabled()Z
+ move-result v$freeRegister
+ if-eqz v$freeRegister, :disabled
+ ${oMethod.toInvokeInstructionString()}
+ ${pMethod.toInvokeInstructionString()}
+ """,
+ listOf(ExternalLabel("disabled", instruction(insertIndex)))
+ )
+ }
+ } ?: return SeekbarTappingFingerprint.toErrorResult()
- val elseLabel = implementation.newLabelForIndex(insertIndex)
- // the instructions are written in reverse order.
- result.mutableMethod.addInstructions(
- insertIndex, """
- invoke-virtual { v$register, v2 }, ${oMethod.definingClass}->${oMethod.name}(I)V
- invoke-virtual { v$register, v2 }, ${pMethod.definingClass}->${pMethod.name}(I)V
- """
- )
-
- // if tap-seeking is disabled, do not invoke the two methods above by jumping to the else label
- implementation.addInstruction(
- insertIndex, BuilderInstruction21t(Opcode.IF_EQZ, 0, elseLabel)
- )
- result.mutableMethod.addInstructions(
- insertIndex, """
- invoke-static { }, Lapp/revanced/integrations/patches/SeekbarTappingPatch;->isTapSeekingEnabled()Z
- move-result v0
- """
- )
return PatchResultSuccess()
}
-}
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingResourcePatch.kt
new file mode 100644
index 000000000..d2281ad27
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingResourcePatch.kt
@@ -0,0 +1,38 @@
+package app.revanced.patches.youtube.interaction.seekbar.patch
+
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.ResourceContext
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultError
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.ResourcePatch
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patches.shared.settings.preference.impl.StringResource
+import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
+import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+
+@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
+@Version("0.0.1")
+class EnableSeekbarTappingResourcePatch : ResourcePatch {
+ override fun execute(context: ResourceContext): PatchResult {
+ SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
+ SwitchPreference(
+ "revanced_seekbar_tapping",
+ StringResource("revanced_seekbar_tapping_title", "Enable seekbar tapping"),
+ StringResource("revanced_seekbar_tapping_summary_on", "Seekbar tapping is enabled"),
+ StringResource("revanced_seekbar_tapping_summary_off", "Seekbar tapping is disabled")
+ )
+ )
+
+ accessibilityPlayerProgressTime = ResourceMappingPatch.resourceMappings.find {
+ it.name == "accessibility_player_progress_time"
+ }?.id ?: return PatchResultError("Failed to find required resource")
+
+ return PatchResultSuccess()
+ }
+
+ internal companion object {
+ var accessibilityPlayerProgressTime = -1L
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/annotation/SwipeControlsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/annotation/SwipeControlsCompatibility.kt
index cb86f6017..feaa5effc 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/annotation/SwipeControlsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/annotation/SwipeControlsCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.interaction.swipecontrols.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class SwipeControlsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/fingerprints/SwipeControlsHostActivityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/fingerprints/SwipeControlsHostActivityFingerprint.kt
index 25e3ada23..368ba1fdd 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/fingerprints/SwipeControlsHostActivityFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/fingerprints/SwipeControlsHostActivityFingerprint.kt
@@ -4,7 +4,7 @@ package app.revanced.patches.youtube.interaction.swipecontrols.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object SwipeControlsHostActivityFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lapp/revanced/integrations/swipecontrols/SwipeControlsHostActivity;" && methodDef.name == ""
}
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/patch/resource/SwipeControlsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/patch/resource/SwipeControlsResourcePatch.kt
index 01cfffd5d..ee1758e75 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/patch/resource/SwipeControlsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/patch/resource/SwipeControlsResourcePatch.kt
@@ -7,92 +7,80 @@ import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
-import app.revanced.patches.shared.settings.preference.impl.StringResource
-import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.shared.settings.preference.impl.TextPreference
-import app.revanced.patches.shared.settings.preference.impl.InputType
-import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility
+import app.revanced.patches.shared.settings.preference.impl.*
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources
@Name("swipe-controls-resource-patch")
@DependsOn([SettingsPatch::class])
-@SwipeControlsCompatibility
@Version("0.0.1")
class SwipeControlsResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
PreferenceScreen(
- "revanced_swipe_controls", StringResource("revanced_swipe_controls_title", "Swipe controls"), listOf(
+ "revanced_swipe_controls_preference_screen",
+ StringResource("revanced_swipe_controls_preference_screen_title", "Swipe controls"),
+ listOf(
SwitchPreference(
- "revanced_enable_swipe_brightness",
- StringResource("revanced_swipe_brightness_enabled_title", "Enable brightness gesture"),
- true,
+ "revanced_swipe_brightness",
+ StringResource("revanced_swipe_brightness_title", "Enable brightness gesture"),
StringResource("revanced_swipe_brightness_summary_on", "Brightness swipe is enabled"),
StringResource("revanced_swipe_brightness_summary_off", "Brightness swipe is disabled")
),
SwitchPreference(
- "revanced_enable_swipe_volume",
- StringResource("revanced_swipe_volume_enabled_title", "Enable volume gesture"),
- true,
+ "revanced_swipe_volume",
+ StringResource("revanced_swipe_volume_title", "Enable volume gesture"),
StringResource("revanced_swipe_volume_summary_on", "Volume swipe is enabled"),
StringResource("revanced_swipe_volume_summary_off", "Volume swipe is disabled")
),
SwitchPreference(
- "revanced_enable_press_to_swipe",
- StringResource("revanced_press_to_swipe_enabled_title", "Enable press-to-swipe gesture"),
- false,
- StringResource("revanced_press_to_swipe_summary_on", "Press-to-swipe is enabled"),
- StringResource("revanced_press_to_swipe_summary_off", "Press-to-swipe is disabled")
+ "revanced_swipe_press_to_engage",
+ StringResource("revanced_swipe_press_to_engage_title", "Enable press-to-swipe gesture"),
+ StringResource("revanced_swipe_press_to_engage_summary_on", "Press-to-swipe is enabled"),
+ StringResource("revanced_swipe_press_to_engage_summary_off", "Press-to-swipe is disabled")
),
SwitchPreference(
- "revanced_enable_swipe_haptic_feedback",
- StringResource("revanced_swipe_haptic_feedback_enabled_title", "Enable haptic feedback"),
- true,
+ "revanced_swipe_haptic_feedback",
+ StringResource("revanced_swipe_haptic_feedback_title", "Enable haptic feedback"),
StringResource("revanced_swipe_haptic_feedback_summary_on", "Haptic feedback is enabled"),
StringResource("revanced_swipe_haptic_feedback_summary_off", "Haptic feedback is disabled")
),
TextPreference(
"revanced_swipe_overlay_timeout",
StringResource("revanced_swipe_overlay_timeout_title", "Swipe overlay timeout"),
- InputType.NUMBER,
- "500",
StringResource(
"revanced_swipe_overlay_timeout_summary",
"The amount of milliseconds the overlay is visible"
- )
+ ),
+ InputType.NUMBER
),
TextPreference(
- "revanced_swipe_overlay_text_size",
- StringResource("revanced_swipe_overlay_text_size_title", "Swipe overlay text size"),
- InputType.NUMBER,
- "22",
- StringResource("revanced_swipe_overlay_text_size_summary", "The text size for swipe overlay")
+ "revanced_swipe_text_overlay_size",
+ StringResource("revanced_swipe_text_overlay_size_title", "Swipe overlay text size"),
+ StringResource("revanced_swipe_text_overlay_size_summary", "The text size for swipe overlay"),
+ InputType.NUMBER
),
TextPreference(
"revanced_swipe_overlay_background_alpha",
StringResource("revanced_swipe_overlay_background_alpha_title", "Swipe background visibility"),
- InputType.NUMBER,
- "127",
StringResource(
"revanced_swipe_overlay_background_alpha_summary",
"The visibility of swipe overlay background"
- )
+ ),
+ InputType.NUMBER
),
TextPreference(
- "revanced_swipe_magnitude_threshold",
- StringResource("revanced_swipe_magnitude_threshold_title", "Swipe magnitude threshold"),
- InputType.NUMBER,
- "30",
+ "revanced_swipe_threshold",
+ StringResource("revanced_swipe_threshold_title", "Swipe magnitude threshold"),
StringResource(
- "revanced_swipe_magnitude_threshold_summary",
+ "revanced_swipe_threshold_summary",
"The amount of threshold for swipe to occur"
- )
+ ),
+ InputType.NUMBER
)
),
- StringResource("revanced_swipe_controls_summary","Control volume and brightness")
+ StringResource("revanced_swipe_controls_preference_screen_summary","Control volume and brightness")
)
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/annotations/AutoCaptionsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/annotations/AutoCaptionsCompatibility.kt
index 383eb476a..c03a3e7f9 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/annotations/AutoCaptionsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/annotations/AutoCaptionsCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.autocaptions.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class AutoCaptionsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/patch/AutoCaptionsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/patch/AutoCaptionsPatch.kt
index 25e3e8521..675a7369b 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/patch/AutoCaptionsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/patch/AutoCaptionsPatch.kt
@@ -33,11 +33,10 @@ class AutoCaptionsPatch : BytecodePatch(
override fun execute(context: BytecodeContext): PatchResult {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
SwitchPreference(
- "revanced_autocaptions_enabled",
- StringResource("revanced_autocaptions_enabled_title", "Disable auto captions"),
- false,
- StringResource("revanced_autocaptions_summary_on", "Auto captions are disabled"),
- StringResource("revanced_autocaptions_summary_off", "Auto captions are enabled")
+ "revanced_auto_captions",
+ StringResource("revanced_auto_captions_title", "Disable auto captions"),
+ StringResource("revanced_auto_captions_summary_on", "Auto captions are disabled"),
+ StringResource("revanced_auto_captions_summary_off", "Auto captions are enabled")
)
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/annotations/HideButtonsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/annotations/HideButtonsCompatibility.kt
index 444ffa739..112725358 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/annotations/HideButtonsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/annotations/HideButtonsCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.buttons.action.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideButtonsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/patch/HideButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/patch/HideButtonsPatch.kt
index cb2c94c04..073d9b05a 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/patch/HideButtonsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/patch/HideButtonsPatch.kt
@@ -27,34 +27,30 @@ class HideButtonsPatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
PreferenceScreen(
- "revanced_hide_buttons",
- StringResource("revanced_hide_buttons_title", "Hide action buttons"),
+ "revanced_hide_buttons_preference_screen",
+ StringResource("revanced_hide_buttons_preference_screen_title", "Hide action buttons"),
listOf(
SwitchPreference(
"revanced_hide_like_dislike_button",
StringResource("revanced_hide_like_dislike_button_title", "Hide like and dislike buttons"),
- false,
StringResource("revanced_hide_like_dislike_button_summary_on", "Like and dislike buttons are hidden"),
StringResource("revanced_hide_like_dislike_button_summary_off", "Like and dislike buttons are shown")
),
SwitchPreference(
"revanced_hide_download_button",
StringResource("revanced_hide_download_button_title", "Hide download button"),
- false,
StringResource("revanced_hide_download_button_summary_on", "Download button is hidden"),
StringResource("revanced_hide_download_button_summary_off", "Download button is shown")
),
SwitchPreference(
"revanced_hide_playlist_button",
StringResource("revanced_hide_playlist_button_title", "Hide playlist button"),
- false,
StringResource("revanced_hide_playlist_button_summary_on", "Playlist button is hidden"),
StringResource("revanced_hide_playlist_button_summary_off", "Playlist button is shown")
),
SwitchPreference(
"revanced_hide_clip_button",
StringResource("revanced_hide_clip_button_title", "Hide clip button"),
- false,
StringResource("revanced_hide_clip_button_summary_on", "Clip button is hidden"),
StringResource("revanced_hide_clip_button_summary_off", "Clip button is shown"),
StringResource("revanced_hide_clip_button_user_dialog_message",
@@ -63,12 +59,11 @@ class HideButtonsPatch : ResourcePatch {
SwitchPreference(
"revanced_hide_action_buttons",
StringResource("revanced_hide_action_buttons_title", "Hide all other action buttons"),
- false,
StringResource("revanced_hide_action_buttons_summary_on", "Share, remix, thanks, shop, live chat buttons are hidden"),
StringResource("revanced_hide_action_buttons_summary_off", "Share, remix, thanks, shop, live chat buttons are shown")
)
),
- StringResource("revanced_hide_buttons_summary", "Hide or show buttons under videos")
+ StringResource("revanced_hide_buttons_preference_screen_summary", "Hide or show buttons under videos")
)
)
return PatchResultSuccess()
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/annotations/AutoplayButtonCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/annotations/AutoplayButtonCompatibility.kt
index 78a4de883..278fb0c2f 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/annotations/AutoplayButtonCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/annotations/AutoplayButtonCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.buttons.autoplay.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class AutoplayButtonCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/fingerprints/LayoutConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/fingerprints/LayoutConstructorFingerprint.kt
index cc9c20ccc..92d33ce31 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/fingerprints/LayoutConstructorFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/fingerprints/LayoutConstructorFingerprint.kt
@@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object LayoutConstructorFingerprint : MethodFingerprint(
strings = listOf("1.0x"),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("YouTubeControlsOverlay;")
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/patch/HideAutoplayButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/patch/HideAutoplayButtonPatch.kt
index 2700bbad9..ff10f48f9 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/patch/HideAutoplayButtonPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/patch/HideAutoplayButtonPatch.kt
@@ -40,7 +40,6 @@ class HideAutoplayButtonPatch : BytecodePatch(
SwitchPreference(
"revanced_hide_autoplay_button",
StringResource("revanced_hide_autoplay_button_title", "Hide autoplay button"),
- true,
StringResource("revanced_hide_autoplay_button_summary_on", "Autoplay button is hidden"),
StringResource("revanced_hide_autoplay_button_summary_off", "Autoplay button is shown")
),
@@ -69,7 +68,7 @@ class HideAutoplayButtonPatch : BytecodePatch(
val jumpInstruction = layoutGenMethodInstructions[insertIndex + branchIndex] as Instruction
// can be clobbered because this register is overwritten after the injected code
- val clobberRegister = (instruction(insertIndex) as OneRegisterInstruction).registerA
+ val clobberRegister = instruction(insertIndex).registerA
addInstructions(
insertIndex,
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/annotations/HideCaptionsButtonCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/annotations/HideCaptionsButtonCompatibility.kt
index c31480999..849d2e18e 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/annotations/HideCaptionsButtonCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/annotations/HideCaptionsButtonCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.buttons.captions.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideCaptionsButtonCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/patch/HideCaptionsButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/patch/HideCaptionsButtonPatch.kt
index fcd7773be..a8aa8dbd3 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/patch/HideCaptionsButtonPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/patch/HideCaptionsButtonPatch.kt
@@ -32,7 +32,6 @@ class HideCaptionsButtonPatch : BytecodePatch(listOf(
SwitchPreference(
"revanced_hide_captions_button",
StringResource("revanced_hide_captions_button_title", "Hide captions button"),
- false,
StringResource("revanced_hide_captions_button_summary_on", "Captions button is hidden"),
StringResource("revanced_hide_captions_button_summary_off", "Captions button is shown")
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/cast/patch/HideCastButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/cast/patch/HideCastButtonPatch.kt
index 884e3adbc..03f57266a 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/cast/patch/HideCastButtonPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/cast/patch/HideCastButtonPatch.kt
@@ -29,7 +29,6 @@ class HideCastButtonPatch : BytecodePatch() {
SwitchPreference(
"revanced_hide_cast_button",
StringResource("revanced_hide_cast_button_title", "Hide cast button"),
- true,
StringResource("revanced_hide_cast_button_summary_on", "Cast button is hidden"),
StringResource("revanced_hide_cast_button_summary_off", "Cast button is shown")
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/annotations/NavigationButtonsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/annotations/NavigationButtonsCompatibility.kt
index 234851058..e298888c1 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/annotations/NavigationButtonsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/annotations/NavigationButtonsCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.buttons.navigation.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class NavigationButtonsCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/InitializeButtonsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/InitializeButtonsFingerprint.kt
index e7c62c85d..33d384042 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/InitializeButtonsFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/InitializeButtonsFingerprint.kt
@@ -6,7 +6,7 @@ import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
object InitializeButtonsFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.implementation?.instructions?.any {
it.opcode == Opcode.CONST && (it as WideLiteralInstruction).wideLiteral ==
ResolvePivotBarFingerprintsPatch.imageOnlyTabResourceId
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarConstructorFingerprint.kt
index 98991910f..4500faf65 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarConstructorFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarConstructorFingerprint.kt
@@ -5,6 +5,6 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
object PivotBarConstructorFingerprint : MethodFingerprint(
- access = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
strings = listOf("com.google.android.apps.youtube.app.endpoint.flags")
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/patch/NavigationButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/patch/NavigationButtonsPatch.kt
index 4a2f584ab..477fdf269 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/patch/NavigationButtonsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/patch/NavigationButtonsPatch.kt
@@ -41,27 +41,24 @@ class NavigationButtonsPatch : BytecodePatch(listOf(AddCreateButtonViewFingerpri
override fun execute(context: BytecodeContext): PatchResult {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
PreferenceScreen(
- "revanced_navigation_buttons",
- StringResource("revanced_navigation_buttons", "Navigation button settings"),
+ "revanced_navigation_buttons_preference_screen",
+ StringResource("revanced_navigation_buttons_preference_screen_title", "Navigation button settings"),
listOf(
SwitchPreference(
"revanced_hide_home_button",
StringResource("revanced_hide_home_button_title", "Hide home button"),
- false,
StringResource("revanced_hide_home_button_summary_on", "Home button is hidden"),
StringResource("revanced_hide_home_button_summary_off", "Home button is shown")
),
SwitchPreference(
"revanced_hide_shorts_button",
StringResource("revanced_hide_shorts_button_title", "Hide shorts button"),
- true,
StringResource("revanced_hide_shorts_button_summary_on", "Shorts button is hidden"),
StringResource("revanced_hide_shorts_button_summary_off", "Shorts button is shown")
),
SwitchPreference(
"revanced_hide_subscriptions_button",
StringResource("revanced_hide_subscriptions_button_title", "Hide subscriptions button"),
- false,
StringResource(
"revanced_hide_subscriptions_button_summary_on",
"Home subscriptions is hidden"
@@ -71,7 +68,6 @@ class NavigationButtonsPatch : BytecodePatch(listOf(AddCreateButtonViewFingerpri
SwitchPreference(
"revanced_hide_create_button",
StringResource("revanced_hide_create_button_title", "Hide create button"),
- true,
StringResource("revanced_hide_create_button_summary_on", "Create button is hidden"),
StringResource("revanced_hide_create_button_summary_off", "Create button is shown")
),
@@ -81,7 +77,6 @@ class NavigationButtonsPatch : BytecodePatch(listOf(AddCreateButtonViewFingerpri
"revanced_switch_create_with_notifications_button_title",
"Switch create with notifications button"
),
- true,
StringResource(
"revanced_switch_create_with_notifications_button_summary_on",
"Create button is switched with notifications"
@@ -149,7 +144,7 @@ class NavigationButtonsPatch : BytecodePatch(listOf(AddCreateButtonViewFingerpri
}!!.index
val conditionalCheckIndex = stringIndex - 1
- val conditionRegister = (instruction(conditionalCheckIndex) as OneRegisterInstruction).registerA
+ val conditionRegister = instruction(conditionalCheckIndex).registerA
addInstructions(
conditionalCheckIndex,
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/utils/InjectionUtils.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/utils/InjectionUtils.kt
index ae60c1aa7..98036c67e 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/utils/InjectionUtils.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/utils/InjectionUtils.kt
@@ -20,7 +20,7 @@ internal object InjectionUtils {
// Register to pass to the hook
val registerIndex = insertIndex - 1 // MOVE_RESULT_OBJECT is always the previous instruction
- val register = (injectTarget.instruction(registerIndex) as OneRegisterInstruction).registerA
+ val register = injectTarget.instruction(registerIndex).registerA
injectTarget.addInstruction(
insertIndex,
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/background/annotations/PlayerButtonBackgroundCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/background/annotations/PlayerButtonBackgroundCompatibility.kt
index ecae5d525..a939d9b7e 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/background/annotations/PlayerButtonBackgroundCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/background/annotations/PlayerButtonBackgroundCompatibility.kt
@@ -2,22 +2,6 @@ package app.revanced.patches.youtube.layout.buttons.player.background.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class PlayerButtonBackgroundCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/background/patch/PlayerButtonBackgroundPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/background/patch/PlayerButtonBackgroundPatch.kt
index b9951abd4..ead1c8658 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/background/patch/PlayerButtonBackgroundPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/background/patch/PlayerButtonBackgroundPatch.kt
@@ -12,16 +12,12 @@ import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.youtube.layout.buttons.player.background.annotations.PlayerButtonBackgroundCompatibility
import org.w3c.dom.Element
-@Patch
+@Patch(false)
@Name("remove-player-button-background")
@Description("Removes the background from the video player buttons.")
@PlayerButtonBackgroundCompatibility
@Version("0.0.1")
class PlayerButtonBackgroundPatch : ResourcePatch {
- private companion object {
- const val RESOURCE_FILE_PATH = "res/drawable/player_button_circle_background.xml"
- }
-
override fun execute(context: ResourceContext): PatchResult {
context.xmlEditor[RESOURCE_FILE_PATH].use { editor ->
editor.file.doRecursively node@{ node ->
@@ -35,4 +31,8 @@ class PlayerButtonBackgroundPatch : ResourcePatch {
return PatchResultSuccess()
}
+
+ private companion object {
+ const val RESOURCE_FILE_PATH = "res/drawable/player_button_circle_background.xml"
+ }
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/annotations/HidePlayerButtonsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/annotations/HidePlayerButtonsCompatibility.kt
index d2137b01c..1f20ff2fb 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/annotations/HidePlayerButtonsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/annotations/HidePlayerButtonsCompatibility.kt
@@ -3,10 +3,6 @@ package app.revanced.patches.youtube.layout.buttons.player.hide.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf()
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HidePlayerButtonsCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/patch/HidePlayerButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/patch/HidePlayerButtonsPatch.kt
index 1ea9cfbad..3b22d811c 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/patch/HidePlayerButtonsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/patch/HidePlayerButtonsPatch.kt
@@ -41,7 +41,6 @@ class HidePlayerButtonsPatch : BytecodePatch(
"revanced_hide_player_buttons_title",
"Hide previous & next video buttons"
),
- false,
StringResource(
"revanced_hide_player_buttons_summary_on",
"Buttons are hidden"
@@ -55,7 +54,7 @@ class HidePlayerButtonsPatch : BytecodePatch(
PlayerControlsVisibilityModelFingerprint.result?.apply {
val callIndex = scanResult.patternScanResult!!.endIndex
- val callInstruction = mutableMethod.instruction(callIndex) as Instruction3rc
+ val callInstruction = mutableMethod.instruction(callIndex)
// overriding this parameter register hides the previous and next buttons
val hasNextParameterRegister = callInstruction.startRegister + ParameterOffsets.HAS_NEXT
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/annotations/AlbumCardsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/annotations/AlbumCardsCompatibility.kt
index 8ea55f844..1523ca1c2 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/annotations/AlbumCardsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/annotations/AlbumCardsCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.albumcards.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class AlbumCardsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/bytecode/fingerprints/AlbumCardsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/bytecode/fingerprints/AlbumCardsFingerprint.kt
index 79874b37a..9382220c2 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/bytecode/fingerprints/AlbumCardsFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/bytecode/fingerprints/AlbumCardsFingerprint.kt
@@ -14,7 +14,7 @@ object AlbumCardsFingerprint : MethodFingerprint(
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.implementation?.instructions?.any { instruction ->
instruction.opcode.ordinal == Opcode.CONST.ordinal &&
(instruction as? WideLiteralInstruction)?.wideLiteral == AlbumCardsResourcePatch.albumCardId
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/bytecode/patch/AlbumCardsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/bytecode/patch/AlbumCardsPatch.kt
index f9ae2950e..bebceae5f 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/bytecode/patch/AlbumCardsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/bytecode/patch/AlbumCardsPatch.kt
@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.layout.hide.albumcards.bytecode.patch
+import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
@@ -29,16 +30,22 @@ class AlbumCardsPatch : BytecodePatch(
)
) {
override fun execute(context: BytecodeContext): PatchResult {
- val albumCardsResult = AlbumCardsFingerprint.result!!
- val albumCardsMethod = albumCardsResult.mutableMethod
+ AlbumCardsFingerprint.result?.let {
+ it.mutableMethod.apply {
+ val checkCastAnchorIndex = it.scanResult.patternScanResult!!.endIndex
+ val insertIndex = checkCastAnchorIndex + 1
- val checkCastAnchorIndex = albumCardsResult.scanResult.patternScanResult!!.endIndex
+ val albumCardViewRegister = instruction(checkCastAnchorIndex).registerA
- albumCardsMethod.addInstruction(
- checkCastAnchorIndex + 1, """
- invoke-static {v${(albumCardsMethod.instruction(checkCastAnchorIndex) as OneRegisterInstruction).registerA}}, Lapp/revanced/integrations/patches/HideAlbumCardsPatch;->hideAlbumCards(Landroid/view/View;)V
- """
- )
+ addInstruction(
+ insertIndex,
+ "invoke-static {v$albumCardViewRegister}, " +
+ "Lapp/revanced/integrations/patches/HideAlbumCardsPatch;" +
+ "->" +
+ "hideAlbumCards(Landroid/view/View;)V"
+ )
+ }
+ } ?: return AlbumCardsFingerprint.toErrorResult()
return PatchResultSuccess()
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/resource/patch/AlbumCardsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/resource/patch/AlbumCardsResourcePatch.kt
index 50621ee06..8193f3f7f 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/resource/patch/AlbumCardsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/resource/patch/AlbumCardsResourcePatch.kt
@@ -27,7 +27,6 @@ class AlbumCardsResourcePatch : ResourcePatch {
SwitchPreference(
"revanced_hide_album_cards",
StringResource("revanced_hide_album_cards_title", "Hide album cards"),
- false,
StringResource("revanced_hide_album_cards_summary_on", "Album cards are hidden"),
StringResource("revanced_hide_album_cards_summary_off", "Album cards are shown")
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/artistcards/annotations/HideArtistCardCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/artistcards/annotations/HideArtistCardCompatibility.kt
index ad3edf3cc..b3245b815 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/artistcards/annotations/HideArtistCardCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/artistcards/annotations/HideArtistCardCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.artistcards.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideArtistCardCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/artistcards/patch/HideArtistCardsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/artistcards/patch/HideArtistCardsPatch.kt
index c6153f34e..e4921df9e 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/artistcards/patch/HideArtistCardsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/artistcards/patch/HideArtistCardsPatch.kt
@@ -28,7 +28,6 @@ class HideArtistCardsPatch : ResourcePatch {
SwitchPreference(
"revanced_hide_artist_cards",
StringResource("revanced_hide_artist_cards_title", "Hide artist cards"),
- false,
StringResource("revanced_hide_artist_cards_on", "Artist cards is hidden"),
StringResource("revanced_hide_artist_cards_off", "Artist cards is shown")
),
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/annotations/BreakingNewsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/annotations/BreakingNewsCompatibility.kt
index 95fd3e7e8..af446cfe8 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/annotations/BreakingNewsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/annotations/BreakingNewsCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.breakingnews.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class BreakingNewsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/bytecode/fingerprints/BreakingNewsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/bytecode/fingerprints/BreakingNewsFingerprint.kt
index b4c3d8363..eb54fbdb6 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/bytecode/fingerprints/BreakingNewsFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/bytecode/fingerprints/BreakingNewsFingerprint.kt
@@ -14,7 +14,7 @@ object BreakingNewsFingerprint : MethodFingerprint(
Opcode.CHECK_CAST,
Opcode.IPUT_OBJECT,
),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.implementation?.instructions?.any { instruction ->
instruction.opcode.ordinal == Opcode.CONST.ordinal &&
(instruction as? WideLiteralInstruction)?.wideLiteral == BreakingNewsResourcePatch.horizontalCardListId
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/bytecode/patch/BreakingNewsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/bytecode/patch/BreakingNewsPatch.kt
index 0b5cf1182..d11423ed3 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/bytecode/patch/BreakingNewsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/bytecode/patch/BreakingNewsPatch.kt
@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.layout.hide.breakingnews.bytecode.patch
+import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
@@ -24,22 +25,29 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@BreakingNewsCompatibility
@Version("0.0.1")
class BreakingNewsPatch : BytecodePatch(
- listOf(
- BreakingNewsFingerprint,
- )
+ listOf(BreakingNewsFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
- val breakingNewsResult = BreakingNewsFingerprint.result!!
- val breakingNewsMethod = breakingNewsResult.mutableMethod
+ BreakingNewsFingerprint.result?.let {
+ val insertIndex = it.scanResult.patternScanResult!!.endIndex - 1
+ val moveResultIndex = insertIndex - 1
- val moveResultObjectIndex =
- breakingNewsResult.scanResult.patternScanResult!!.endIndex - 2
+ it.mutableMethod.apply {
+ val breakingNewsViewRegister = instruction(moveResultIndex).registerA
+
+ addInstruction(
+ insertIndex,
+ """
+ invoke-static {v$breakingNewsViewRegister},
+ Lapp/revanced/integrations/patches/HideBreakingNewsPatch;
+ ->
+ hideBreakingNews(Landroid/view/View;)V
+ """
+ )
+ }
+
+ } ?: return BreakingNewsFingerprint.toErrorResult()
- breakingNewsMethod.addInstruction(
- moveResultObjectIndex + 1, """
- invoke-static {v${(breakingNewsMethod.instruction(moveResultObjectIndex) as OneRegisterInstruction).registerA}}, Lapp/revanced/integrations/patches/HideBreakingNewsPatch;->hideBreakingNews(Landroid/view/View;)V
- """
- )
return PatchResultSuccess()
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/resource/patch/BreakingNewsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/resource/patch/BreakingNewsResourcePatch.kt
index ffb32092e..f310ac764 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/resource/patch/BreakingNewsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/resource/patch/BreakingNewsResourcePatch.kt
@@ -25,7 +25,6 @@ class BreakingNewsResourcePatch : ResourcePatch {
SwitchPreference(
"revanced_hide_breaking_news",
StringResource("revanced_hide_breaking_news_title", "Hide breaking news"),
- true,
StringResource("revanced_hide_breaking_news_summary_on", "Breaking news are hidden"),
StringResource("revanced_hide_breaking_news_summary_off", "Breaking news are shown")
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/annotations/CommentsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/annotations/CommentsCompatibility.kt
deleted file mode 100644
index c852dc42b..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/annotations/CommentsCompatibility.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.comments.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class CommentsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/annotations/HideCommentsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/annotations/HideCommentsCompatibility.kt
new file mode 100644
index 000000000..27f8151f0
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/annotations/HideCommentsCompatibility.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.youtube.layout.hide.comments.annotations
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
+@Target(AnnotationTarget.CLASS)
+internal annotation class HideCommentsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/bytecode/fingerprints/ShortsCommentsButtonFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/bytecode/fingerprints/ShortsCommentsButtonFingerprint.kt
deleted file mode 100644
index 1bfb297f3..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/bytecode/fingerprints/ShortsCommentsButtonFingerprint.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.comments.bytecode.fingerprints
-
-import app.revanced.patcher.extensions.or
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import app.revanced.patches.youtube.layout.hide.comments.resource.patch.CommentsResourcePatch
-import org.jf.dexlib2.AccessFlags
-import org.jf.dexlib2.Opcode
-import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
-
-object ShortsCommentsButtonFingerprint : MethodFingerprint(
- "V", AccessFlags.PRIVATE or AccessFlags.FINAL, listOf("Z", "Z", "L"),
- customFingerprint = { methodDef ->
- methodDef.implementation?.instructions?.any {
- it.opcode.ordinal == Opcode.CONST.ordinal && (it as WideLiteralInstruction).wideLiteral == CommentsResourcePatch.shortsCommentsButtonId
- } == true
- }
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/bytecode/patch/CommentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/bytecode/patch/CommentsPatch.kt
deleted file mode 100644
index 7e6708278..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/bytecode/patch/CommentsPatch.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.comments.bytecode.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.annotation.Version
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.addInstructions
-import app.revanced.patcher.extensions.instruction
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.PatchResult
-import app.revanced.patcher.patch.PatchResultSuccess
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.layout.hide.comments.annotations.CommentsCompatibility
-import app.revanced.patches.youtube.layout.hide.comments.bytecode.fingerprints.ShortsCommentsButtonFingerprint
-import app.revanced.patches.youtube.layout.hide.comments.resource.patch.CommentsResourcePatch
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import org.jf.dexlib2.Opcode
-import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
-
-@Patch
-@DependsOn([IntegrationsPatch::class, CommentsResourcePatch::class])
-@Name("comments")
-@Description("Hides components related to comments.")
-@CommentsCompatibility
-@Version("0.0.1")
-class CommentsPatch : BytecodePatch(
- listOf(
- ShortsCommentsButtonFingerprint
- )
-) {
- override fun execute(context: BytecodeContext): PatchResult {
- val shortsCommentsButtonResult = ShortsCommentsButtonFingerprint.result!!
- val shortsCommentsButtonMethod = shortsCommentsButtonResult.mutableMethod
-
- val checkCastAnchorFingerprint = object : MethodFingerprint(
- opcodes = listOf(
- Opcode.CONST,
- Opcode.CONST_HIGH16,
- Opcode.IF_EQZ,
- Opcode.CONST,
- Opcode.INVOKE_STATIC,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.CHECK_CAST,
- )
- ) {}
-
- val checkCastAnchorIndex = checkCastAnchorFingerprint.also {
- it.resolve(context, shortsCommentsButtonMethod, shortsCommentsButtonResult.classDef)
- }.result!!.scanResult.patternScanResult!!.endIndex
-
- shortsCommentsButtonMethod.addInstructions(
- checkCastAnchorIndex + 1, """
- invoke-static {v${(shortsCommentsButtonMethod.instruction(checkCastAnchorIndex) as OneRegisterInstruction).registerA}}, Lapp/revanced/integrations/patches/HideShortsCommentsButtonPatch;->hideShortsCommentsButton(Landroid/view/View;)V
- """
- )
-
- return PatchResultSuccess()
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/resource/patch/CommentsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/patch/CommentsPatch.kt
similarity index 61%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/resource/patch/CommentsResourcePatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/patch/CommentsPatch.kt
index c16d6f82e..5ebb44d14 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/resource/patch/CommentsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/patch/CommentsPatch.kt
@@ -1,5 +1,6 @@
-package app.revanced.patches.youtube.layout.hide.comments.resource.patch
+package app.revanced.patches.youtube.layout.hide.comments.patch
+import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext
@@ -7,58 +8,44 @@ import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.hide.comments.annotations.CommentsCompatibility
+import app.revanced.patches.youtube.layout.hide.comments.annotations.HideCommentsCompatibility
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-@Name("comments-resource-patch")
-@CommentsCompatibility
+@Patch
+@Name("comments")
+@Description("Hides components related to comments.")
+@HideCommentsCompatibility
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
@Version("0.0.1")
-class CommentsResourcePatch : ResourcePatch {
- companion object {
- internal var shortsCommentsButtonId: Long = -1
- }
-
+class CommentsPatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
PreferenceScreen(
- "revanced_comments",
- StringResource("revanced_comments_title", "Comments"),
+ "revanced_comments_preference_screen",
+ StringResource("revanced_comments_preference_screen_title", "Comments"),
listOf(
SwitchPreference(
"revanced_hide_comments_section",
StringResource("revanced_hide_comments_section_title", "Hide comments section"),
- false,
StringResource("revanced_hide_comments_section_summary_on", "Comment section is hidden"),
StringResource("revanced_hide_comments_section_summary_off", "Comment section is shown")
),
SwitchPreference(
"revanced_hide_preview_comment",
StringResource("revanced_hide_preview_comment_title", "Hide preview comment"),
- false,
StringResource("revanced_hide_preview_comment_on", "Preview comment is hidden"),
StringResource("revanced_hide_preview_comment_off", "Preview comment is shown")
- ),
- SwitchPreference(
- "revanced_hide_shorts_comments_button",
- StringResource("revanced_hide_shorts_comments_button_title", "Hide shorts comments button"),
- false,
- StringResource("revanced_hide_shorts_comments_button_on", "Shorts comments button is hidden"),
- StringResource("revanced_hide_shorts_comments_button_off", "Shorts comments button is shown")
- ),
+ )
),
- StringResource("revanced_comments_summary", "Manage the visibility of comments section components")
+ StringResource("revanced_comments_preference_screen_summary", "Manage the visibility of comments section components")
)
)
- shortsCommentsButtonId = ResourceMappingPatch.resourceMappings.single {
- it.type == "drawable" && it.name == "ic_right_comment_32c"
- }.id
-
return PatchResultSuccess()
}
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/annotations/CrowdfundingBoxCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/annotations/CrowdfundingBoxCompatibility.kt
index 70629074e..f6776877b 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/annotations/CrowdfundingBoxCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/annotations/CrowdfundingBoxCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.crowdfundingbox.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class CrowdfundingBoxCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/fingerprints/CrowdfundingBoxFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/fingerprints/CrowdfundingBoxFingerprint.kt
index 0ad96367d..1ed367227 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/fingerprints/CrowdfundingBoxFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/fingerprints/CrowdfundingBoxFingerprint.kt
@@ -11,7 +11,7 @@ object CrowdfundingBoxFingerprint : MethodFingerprint(
Opcode.MOVE_RESULT_OBJECT,
Opcode.IPUT_OBJECT,
),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.implementation?.instructions?.any { instruction ->
instruction.opcode.ordinal == Opcode.CONST.ordinal &&
(instruction as? WideLiteralInstruction)?.wideLiteral == CrowdfundingBoxResourcePatch.crowdfundingBoxId
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/patch/CrowdfundingBoxPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/patch/CrowdfundingBoxPatch.kt
index 94d3b103f..c6373f635 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/patch/CrowdfundingBoxPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/patch/CrowdfundingBoxPatch.kt
@@ -33,7 +33,7 @@ class CrowdfundingBoxPatch : BytecodePatch(
CrowdfundingBoxFingerprint.result?.let {
it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.endIndex
- val objectRegister = (instruction(insertIndex) as TwoRegisterInstruction).registerA
+ val objectRegister = instruction(insertIndex).registerA
addInstruction(insertIndex, "invoke-static {v$objectRegister}, $INTEGRATIONS_METHOD_DESCRIPTOR")
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/resource/patch/CrowdfundingBoxResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/resource/patch/CrowdfundingBoxResourcePatch.kt
index dc639f438..feb830194 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/resource/patch/CrowdfundingBoxResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/resource/patch/CrowdfundingBoxResourcePatch.kt
@@ -27,7 +27,6 @@ class CrowdfundingBoxResourcePatch : ResourcePatch {
SwitchPreference(
"revanced_hide_crowdfunding_box",
StringResource("revanced_hide_crowdfunding_box_title", "Hide crowdfunding box"),
- false,
StringResource("revanced_hide_crowdfunding_box_summary_on", "Crowdfunding box is hidden"),
StringResource("revanced_hide_crowdfunding_box_summary_off", "Crowdfunding box is shown")
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/annotations/HideEndscreenCardsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/annotations/HideEndscreenCardsCompatibility.kt
index c0c561520..47d278010 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/annotations/HideEndscreenCardsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/annotations/HideEndscreenCardsCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.endscreencards.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideEndscreenCardsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutCircleFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutCircleFingerprint.kt
index 0931de5f1..55521394a 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutCircleFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutCircleFingerprint.kt
@@ -13,7 +13,7 @@ object LayoutCircleFingerprint : MethodFingerprint(
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.implementation?.instructions?.any { instruction ->
instruction.opcode.ordinal == Opcode.CONST.ordinal &&
(instruction as? WideLiteralInstruction)?.wideLiteral == HideEndscreenCardsResourcePatch.layoutCircle
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutIconFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutIconFingerprint.kt
index 9fcd0dc43..603bebdd3 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutIconFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutIconFingerprint.kt
@@ -13,7 +13,7 @@ object LayoutIconFingerprint : MethodFingerprint(
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.implementation?.instructions?.any { instruction ->
instruction.opcode.ordinal == Opcode.CONST.ordinal &&
(instruction as? WideLiteralInstruction)?.wideLiteral == HideEndscreenCardsResourcePatch.layoutIcon
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutVideoFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutVideoFingerprint.kt
index bec34caf5..01307ad6c 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutVideoFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/fingerprints/LayoutVideoFingerprint.kt
@@ -13,7 +13,7 @@ object LayoutVideoFingerprint : MethodFingerprint(
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.implementation?.instructions?.any { instruction ->
instruction.opcode.ordinal == Opcode.CONST.ordinal &&
(instruction as? WideLiteralInstruction)?.wideLiteral == HideEndscreenCardsResourcePatch.layoutVideo
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/patch/HideEndscreenCardsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/patch/HideEndscreenCardsPatch.kt
index 69adc82c6..624e3c4eb 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/patch/HideEndscreenCardsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/bytecode/patch/HideEndscreenCardsPatch.kt
@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.layout.hide.endscreencards.bytecode.patch
+import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
@@ -35,19 +36,23 @@ class HideEndscreenCardsPatch : BytecodePatch(
) {
override fun execute(context: BytecodeContext): PatchResult {
fun MethodFingerprint.injectHideCall() {
- val layoutResult = result!!
- val layoutMethod = layoutResult.mutableMethod
+ val layoutResult = result ?: throw toErrorResult()
+ layoutResult.mutableMethod.apply {
+ val insertIndex = layoutResult.scanResult.patternScanResult!!.endIndex + 1
+ val viewRegister = instruction(insertIndex - 1).registerA
- val checkCastIndex = layoutResult.scanResult.patternScanResult!!.endIndex
- val viewRegister = (layoutMethod.instruction(checkCastIndex) as Instruction21c).registerA
-
- layoutMethod.addInstruction(
- checkCastIndex + 1,
- "invoke-static { v$viewRegister }, Lapp/revanced/integrations/patches/HideEndscreenCardsPatch;->hideEndscreen(Landroid/view/View;)V"
- )
+ addInstruction(
+ insertIndex,
+ "invoke-static { v$viewRegister }, Lapp/revanced/integrations/patches/HideEndscreenCardsPatch;->hideEndscreen(Landroid/view/View;)V"
+ )
+ }
}
-
- listOf(LayoutCircleFingerprint, LayoutIconFingerprint, LayoutVideoFingerprint).forEach(MethodFingerprint::injectHideCall)
+
+ listOf(
+ LayoutCircleFingerprint,
+ LayoutIconFingerprint,
+ LayoutVideoFingerprint
+ ).forEach(MethodFingerprint::injectHideCall)
return PatchResultSuccess()
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/resource/patch/HideEndscreenCardsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/resource/patch/HideEndscreenCardsResourcePatch.kt
index 6dc3d74c5..5919bb5b6 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/resource/patch/HideEndscreenCardsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/resource/patch/HideEndscreenCardsResourcePatch.kt
@@ -29,7 +29,6 @@ class HideEndscreenCardsResourcePatch : ResourcePatch {
SwitchPreference(
"revanced_hide_endscreen_cards",
StringResource("revanced_hide_endscreen_cards_title", "Hide end screen cards"),
- true,
StringResource("revanced_hide_endscreen_cards_summary_on", "End screen cards are hidden"),
StringResource("revanced_hide_endscreen_cards_summary_off", "End screen cards are shown")
),
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/annotations/HideFilterBar.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/annotations/HideFilterBar.kt
new file mode 100644
index 000000000..e45cafd7b
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/annotations/HideFilterBar.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.youtube.layout.hide.filterbar.annotations
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
+@Target(AnnotationTarget.CLASS)
+internal annotation class HideFilterBar
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/FilterBarHeightFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/FilterBarHeightFingerprint.kt
new file mode 100644
index 000000000..6178c4c89
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/FilterBarHeightFingerprint.kt
@@ -0,0 +1,14 @@
+package app.revanced.patches.youtube.layout.hide.filterbar.fingerprints
+
+import app.revanced.patches.youtube.layout.hide.filterbar.patch.HideFilterBarResourcePatch.Companion.filterBarHeightId
+import org.jf.dexlib2.Opcode
+
+object FilterBarHeightFingerprint : LiteralOpcodesFingerprint(
+ opcodes = listOf(
+ Opcode.CONST,
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.MOVE_RESULT,
+ Opcode.IPUT
+ ),
+ filterBarHeightId
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/LiteralOpcodesFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/LiteralOpcodesFingerprint.kt
new file mode 100644
index 000000000..3189e17ec
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/LiteralOpcodesFingerprint.kt
@@ -0,0 +1,19 @@
+package app.revanced.patches.youtube.layout.hide.filterbar.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import org.jf.dexlib2.Opcode
+import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
+
+
+abstract class LiteralOpcodesFingerprint(opcodes: List, literal: Long) : MethodFingerprint(
+ opcodes = opcodes,
+ customFingerprint = { methodDef, _ ->
+ methodDef.implementation?.instructions?.any { instruction ->
+ if (instruction.opcode != Opcode.CONST) return@any false
+
+ val wideLiteral = (instruction as WideLiteralInstruction).wideLiteral
+
+ literal == wideLiteral
+ } ?: false
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/RelatedChipCloudFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/RelatedChipCloudFingerprint.kt
new file mode 100644
index 000000000..be0ef5cee
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/RelatedChipCloudFingerprint.kt
@@ -0,0 +1,13 @@
+package app.revanced.patches.youtube.layout.hide.filterbar.fingerprints
+
+import app.revanced.patches.youtube.layout.hide.filterbar.patch.HideFilterBarResourcePatch.Companion.relatedChipCloudMarginId
+import org.jf.dexlib2.Opcode
+
+object RelatedChipCloudFingerprint : LiteralOpcodesFingerprint(
+ opcodes = listOf(
+ Opcode.CONST,
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.MOVE_RESULT_OBJECT
+ ),
+ relatedChipCloudMarginId
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/SearchResultsChipBarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/SearchResultsChipBarFingerprint.kt
new file mode 100644
index 000000000..82deee685
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/fingerprints/SearchResultsChipBarFingerprint.kt
@@ -0,0 +1,15 @@
+package app.revanced.patches.youtube.layout.hide.filterbar.fingerprints
+
+import app.revanced.patches.youtube.layout.hide.filterbar.patch.HideFilterBarResourcePatch.Companion.barContainerHeightId
+import org.jf.dexlib2.Opcode
+
+object SearchResultsChipBarFingerprint : LiteralOpcodesFingerprint(
+ opcodes = listOf(
+ Opcode.CONST,
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.MOVE_RESULT,
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.MOVE_RESULT_OBJECT
+ ),
+ barContainerHeightId
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/patch/HideFilterBarPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/patch/HideFilterBarPatch.kt
new file mode 100644
index 000000000..ea69ddbe3
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/patch/HideFilterBarPatch.kt
@@ -0,0 +1,87 @@
+package app.revanced.patches.youtube.layout.hide.filterbar.patch
+
+import app.revanced.extensions.toErrorResult
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.extensions.instruction
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patches.youtube.layout.hide.filterbar.annotations.HideFilterBar
+import app.revanced.patches.youtube.layout.hide.filterbar.fingerprints.FilterBarHeightFingerprint
+import app.revanced.patches.youtube.layout.hide.filterbar.fingerprints.RelatedChipCloudFingerprint
+import app.revanced.patches.youtube.layout.hide.filterbar.fingerprints.SearchResultsChipBarFingerprint
+import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
+import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
+
+@Patch
+@Name("hide-filter-bar")
+@Description("Hides the filter bar in video feeds.")
+@DependsOn([HideFilterBarResourcePatch::class])
+@HideFilterBar
+@Version("0.0.1")
+class HideFilterBarPatch : BytecodePatch(
+ listOf(
+ RelatedChipCloudFingerprint,
+ SearchResultsChipBarFingerprint,
+ FilterBarHeightFingerprint
+ )
+) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ FilterBarHeightFingerprint.patch { register ->
+ """
+ invoke-static { v$register }, $INTEGRATIONS_CLASS_DESCRIPTOR->hideInFeed(I)I
+ move-result v$register
+ """
+ }
+
+ RelatedChipCloudFingerprint.patch(1) { register ->
+ "invoke-static { v$register }, " +
+ "$INTEGRATIONS_CLASS_DESCRIPTOR->hideInRelatedVideos(Landroid/view/View;)V"
+ }
+
+ SearchResultsChipBarFingerprint.patch(-1, -2) { register ->
+ """
+ invoke-static { v$register }, $INTEGRATIONS_CLASS_DESCRIPTOR->hideInSearch(I)I
+ move-result v$register
+ """
+ }
+
+ return PatchResultSuccess()
+ }
+
+ private companion object {
+ const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/HideFilterBarPatch;"
+
+ /**
+ * Patch a [MethodFingerprint] with a given [instructions].
+ *
+ * @param RegisterInstruction The type of instruction to get the register from.
+ * @param insertIndexOffset The offset to add to the end index of the [MethodFingerprint].
+ * @param hookRegisterOffset The offset to add to the register of the hook.
+ * @param instructions The instructions to add with the register as a parameter.
+ */
+ private fun MethodFingerprint.patch(
+ insertIndexOffset: Int = 0,
+ hookRegisterOffset: Int = 0,
+ instructions: (Int) -> String
+ ) =
+ result?.let {
+ it.mutableMethod.apply {
+ val endIndex = it.scanResult.patternScanResult!!.endIndex
+
+ val insertIndex = endIndex + insertIndexOffset
+ val register = instruction(endIndex + hookRegisterOffset).registerA
+
+ addInstructions(insertIndex, instructions(register))
+ }
+ } ?: throw toErrorResult()
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/patch/HideFilterBarResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/patch/HideFilterBarResourcePatch.kt
new file mode 100644
index 000000000..45bddf581
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/patch/HideFilterBarResourcePatch.kt
@@ -0,0 +1,95 @@
+package app.revanced.patches.youtube.layout.hide.filterbar.patch
+
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.ResourceContext
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.ResourcePatch
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
+import app.revanced.patches.shared.settings.preference.impl.StringResource
+import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
+import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+
+@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
+@Version("0.0.1")
+class HideFilterBarResourcePatch : ResourcePatch {
+ override fun execute(context: ResourceContext): PatchResult {
+ SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
+ PreferenceScreen(
+ "revanced_hide_filter_bar_preference",
+ StringResource(
+ "revanced_hide_filter_bar_preference_title",
+ "Hide filter bar"
+ ),
+ listOf(
+ SwitchPreference(
+ "revanced_hide_filter_bar_feed_in_feed",
+ StringResource(
+ "revanced_hide_filter_bar_feed_in_feed_title",
+ "Hide in feed"
+ ),
+ StringResource(
+ "revanced_hide_filter_bar_feed_in_feed_summary_on",
+ "Hidden in feed"
+ ),
+ StringResource(
+ "revanced_hide_filter_bar_feed_in_feed_summary_off",
+ "Shown in feed"
+ )
+ ),
+ SwitchPreference(
+ "revanced_hide_filter_bar_feed_in_search",
+ StringResource(
+ "revanced_hide_filter_bar_feed_in_search_title",
+ "Hide in search"
+ ),
+ StringResource(
+ "revanced_hide_filter_bar_feed_in_search_summary_on",
+ "Hidden in search"
+ ),
+ StringResource(
+ "revanced_hide_filter_bar_feed_in_search_summary_off",
+ "Shown in search"
+ )
+ ),
+ SwitchPreference(
+ "revanced_hide_filter_bar_feed_in_related_videos",
+ StringResource(
+ "revanced_hide_filter_bar_feed_in_related_videos_title",
+ "Hide in related videos"
+ ),
+ StringResource(
+ "revanced_hide_filter_bar_feed_in_related_videos_summary_on",
+ "Hidden in related videos"
+ ),
+ StringResource(
+ "revanced_hide_filter_bar_feed_in_related_videos_summary_off",
+ "Shown in related videos"
+ )
+ ),
+ ),
+ StringResource(
+ "revanced_hide_filter_bar_preference_summary",
+ "Manage the visibility of the filter bar in the feed, search and related videos"
+ )
+ )
+ )
+
+ relatedChipCloudMarginId = "related_chip_cloud_reduced_margins".layoutResourceId("layout")
+ filterBarHeightId = "filter_bar_height".layoutResourceId()
+ barContainerHeightId = "bar_container_height".layoutResourceId()
+
+ return PatchResultSuccess()
+ }
+
+ internal companion object {
+ var filterBarHeightId = -1L
+ var relatedChipCloudMarginId = -1L
+ var barContainerHeightId = -1L
+
+ private fun String.layoutResourceId(type: String = "dimen") =
+ ResourceMappingPatch.resourceMappings.single { it.type == type && it.name == this }.id
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/annotations/HideFloatingMicrophoneButtonCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/annotations/HideFloatingMicrophoneButtonCompatibility.kt
index ae7f3beeb..8ab0a1e5c 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/annotations/HideFloatingMicrophoneButtonCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/annotations/HideFloatingMicrophoneButtonCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.floatingmicrophone.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideFloatingMicrophoneButtonCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/fingerprints/ShowFloatingMicrophoneButtonFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/fingerprints/ShowFloatingMicrophoneButtonFingerprint.kt
index ed72bd968..276cfbe4b 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/fingerprints/ShowFloatingMicrophoneButtonFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/fingerprints/ShowFloatingMicrophoneButtonFingerprint.kt
@@ -11,7 +11,7 @@ object ShowFloatingMicrophoneButtonFingerprint : MethodFingerprint(
Opcode.IF_EQZ,
Opcode.RETURN_VOID
),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.implementation?.instructions?.any {
(it as? WideLiteralInstruction)?.wideLiteral == HideFloatingMicrophoneButtonResourcePatch.fabButtonId
} == true
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/patch/HideFloatingMicrophoneButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/patch/HideFloatingMicrophoneButtonPatch.kt
index 30f02c143..1d50b18db 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/patch/HideFloatingMicrophoneButtonPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/patch/HideFloatingMicrophoneButtonPatch.kt
@@ -29,7 +29,7 @@ class HideFloatingMicrophoneButtonPatch : BytecodePatch(
ShowFloatingMicrophoneButtonFingerprint.result?.let { result ->
with(result.mutableMethod) {
val insertIndex = result.scanResult.patternScanResult!!.startIndex + 1
- val showButtonRegister = (instruction(insertIndex - 1) as TwoRegisterInstruction).registerA
+ val showButtonRegister = instruction(insertIndex - 1).registerA
addInstructions(
insertIndex,
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/patch/HideFloatingMicrophoneButtonResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/patch/HideFloatingMicrophoneButtonResourcePatch.kt
index 5bc6cc043..ede1d0642 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/patch/HideFloatingMicrophoneButtonResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/patch/HideFloatingMicrophoneButtonResourcePatch.kt
@@ -25,7 +25,6 @@ class HideFloatingMicrophoneButtonResourcePatch : ResourcePatch {
"revanced_hide_floating_microphone_button_enabled_title",
"Hide floating microphone button"
),
- true,
StringResource("revanced_hide_floating_microphone_button_summary_on", "Microphone button hidden"),
StringResource("revanced_hide_floating_microphone_button_summary_off", "Microphone button shown")
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/annotations/HideGetPremiumCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/annotations/HideGetPremiumCompatibility.kt
index 917439846..bd210bfc9 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/annotations/HideGetPremiumCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/annotations/HideGetPremiumCompatibility.kt
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.hide.getpremium.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.15.40", "18.16.37"))])
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideGetPremiumCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/bytecode/fingerprints/GetPremiumViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/bytecode/fingerprints/GetPremiumViewFingerprint.kt
index 29cca3d03..2cffc2377 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/bytecode/fingerprints/GetPremiumViewFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/bytecode/fingerprints/GetPremiumViewFingerprint.kt
@@ -10,7 +10,7 @@ object GetPremiumViewFingerprint : MethodFingerprint(
Opcode.INVOKE_VIRTUAL,
Opcode.RETURN_VOID
),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lcom/google/android/apps/youtube/app/red/presenter/CompactYpcOfferModuleView;"
&& methodDef.name == "onMeasure"
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/bytecode/patch/HideGetPremiumVideoAdvertisementPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/bytecode/patch/HideGetPremiumVideoAdvertisementPatch.kt
index 7e3e7b036..1c978a7c8 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/bytecode/patch/HideGetPremiumVideoAdvertisementPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/getpremium/bytecode/patch/HideGetPremiumVideoAdvertisementPatch.kt
@@ -36,7 +36,6 @@ class HideGetPremiumPatch : BytecodePatch(
SwitchPreference(
"revanced_hide_get_premium",
StringResource("revanced_hide_get_premium_title", "Hide YouTube Premium advertisement"),
- true,
StringResource("revanced_hide_get_premium_summary_on", "YouTube Premium advertisement are hidden"),
StringResource("revanced_hide_get_premium_summary_off", "YouTube Premium advertisement are shown")
)
@@ -45,8 +44,9 @@ class HideGetPremiumPatch : BytecodePatch(
GetPremiumViewFingerprint.result?.let {
it.mutableMethod.apply {
val startIndex = it.scanResult.patternScanResult!!.startIndex
- val measuredWidthRegister = (instruction(startIndex) as TwoRegisterInstruction).registerA
- val measuredHeightInstruction = instruction(startIndex + 1) as TwoRegisterInstruction
+ val measuredWidthRegister = instruction(startIndex).registerA
+ val measuredHeightInstruction = instruction(startIndex + 1)
+
val measuredHeightRegister = measuredHeightInstruction.registerA
val tempRegister = measuredHeightInstruction.registerB
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/annotations/HideInfocardsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/annotations/HideInfocardsCompatibility.kt
index d9c458384..8a71676e9 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/annotations/HideInfocardsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/annotations/HideInfocardsCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.infocards.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideInfocardsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/fingerprints/InfocardsMethodCallFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/fingerprints/InfocardsMethodCallFingerprint.kt
index 0f258ca1b..08f9ed020 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/fingerprints/InfocardsMethodCallFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/fingerprints/InfocardsMethodCallFingerprint.kt
@@ -11,7 +11,7 @@ object InfocardsMethodCallFingerprint : MethodFingerprint(
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.implementation?.instructions?.any { instruction ->
(instruction as? WideLiteralInstruction)?.wideLiteral == HideInfocardsResourcePatch.drawerResourceId
} == true
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/patch/HideInfoCardsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/patch/HideInfoCardsPatch.kt
index 577a4da0d..d47584343 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/patch/HideInfoCardsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/patch/HideInfoCardsPatch.kt
@@ -20,7 +20,8 @@ import app.revanced.patches.youtube.layout.hide.infocards.fingerprints.Infocards
import app.revanced.patches.youtube.layout.hide.infocards.resource.patch.HideInfocardsResourcePatch
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import org.jf.dexlib2.Opcode
-import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
+import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
+import org.jf.dexlib2.iface.instruction.ReferenceInstruction
@Patch
@DependsOn([IntegrationsPatch::class, HideInfocardsResourcePatch::class])
@@ -35,18 +36,17 @@ class HideInfoCardsPatch : BytecodePatch(
)
) {
override fun execute(context: BytecodeContext): PatchResult {
- with(InfocardsIncognitoFingerprint.also {
+ InfocardsIncognitoFingerprint.also {
it.resolve(context, InfocardsIncognitoParentFingerprint.result!!.classDef)
- }.result!!.mutableMethod) {
+ }.result!!.mutableMethod.apply {
val invokeInstructionIndex = implementation!!.instructions.indexOfFirst {
it.opcode.ordinal == Opcode.INVOKE_VIRTUAL.ordinal &&
- ((it as? BuilderInstruction35c)?.reference.toString() ==
- "Landroid/view/View;->setVisibility(I)V")
+ ((it as ReferenceInstruction).reference.toString() == "Landroid/view/View;->setVisibility(I)V")
}
addInstructions(
invokeInstructionIndex,
- "invoke-static {v${(instruction(invokeInstructionIndex) as? BuilderInstruction35c)?.registerC}}," +
+ "invoke-static {v${instruction(invokeInstructionIndex).registerC}}," +
" Lapp/revanced/integrations/patches/HideInfoCardsPatch;->hideInfoCardsIncognito(Landroid/view/View;)V"
)
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/resource/patch/HideInfocardsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/resource/patch/HideInfocardsResourcePatch.kt
index 47388939a..c5aa4049c 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/resource/patch/HideInfocardsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/resource/patch/HideInfocardsResourcePatch.kt
@@ -25,7 +25,6 @@ class HideInfocardsResourcePatch : ResourcePatch {
SwitchPreference(
"revanced_hide_infocards",
StringResource("revanced_hide_infocards_title", "Hide info cards"),
- true,
StringResource("revanced_hide_infocards_summary_on", "Info cards are hidden"),
StringResource("revanced_hide_infocards_summary_off", "Info cards are shown")
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/annotations/HideLoadMoreButtonCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/annotations/HideLoadMoreButtonCompatibility.kt
new file mode 100644
index 000000000..5c580599c
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/annotations/HideLoadMoreButtonCompatibility.kt
@@ -0,0 +1,9 @@
+package app.revanced.patches.youtube.layout.hide.loadmorebutton.annotations
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
+@Target(AnnotationTarget.CLASS)
+internal annotation class HideLoadMoreButtonCompatibility
+
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/bytecode/fingerprints/HideLoadMoreButtonFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/bytecode/fingerprints/HideLoadMoreButtonFingerprint.kt
new file mode 100644
index 000000000..2669411e2
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/bytecode/fingerprints/HideLoadMoreButtonFingerprint.kt
@@ -0,0 +1,29 @@
+package app.revanced.patches.youtube.layout.hide.loadmorebutton.bytecode.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import app.revanced.patches.youtube.layout.hide.loadmorebutton.resource.patch.HideLoadMoreButtonResourcePatch
+import org.jf.dexlib2.AccessFlags
+import org.jf.dexlib2.Opcode
+import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
+
+object HideLoadMoreButtonFingerprint : MethodFingerprint(
+ returnType = "V",
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
+ parameters = listOf("L", "L", "L", "L"),
+ opcodes = listOf(
+ Opcode.CONST,
+ Opcode.CONST_4,
+ Opcode.INVOKE_STATIC,
+ Opcode.MOVE_RESULT_OBJECT
+ ),
+ customFingerprint = { methodDef, _ ->
+ methodDef.implementation?.instructions?.any {
+ if (it.opcode != Opcode.CONST) return@any false
+
+ val literal = (it as WideLiteralInstruction).wideLiteral
+
+ literal == HideLoadMoreButtonResourcePatch.expandButtonDownId
+ } ?: false
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/bytecode/patch/HideLoadMoreButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/bytecode/patch/HideLoadMoreButtonPatch.kt
new file mode 100644
index 000000000..b63f52302
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/bytecode/patch/HideLoadMoreButtonPatch.kt
@@ -0,0 +1,50 @@
+package app.revanced.patches.youtube.layout.hide.loadmorebutton.bytecode.patch
+
+import app.revanced.extensions.toErrorResult
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.addInstruction
+import app.revanced.patcher.extensions.instruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patches.youtube.layout.hide.loadmorebutton.bytecode.fingerprints.HideLoadMoreButtonFingerprint
+import app.revanced.patches.youtube.layout.hide.loadmorebutton.resource.patch.HideLoadMoreButtonResourcePatch
+import app.revanced.patches.youtube.layout.hide.loadmorebutton.annotations.HideLoadMoreButtonCompatibility
+import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
+import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
+
+@Patch
+@Name("hide-load-more-button")
+@Description("Hides the button under videos that loads similar videos.")
+@DependsOn([HideLoadMoreButtonResourcePatch::class])
+@HideLoadMoreButtonCompatibility
+@Version("0.0.1")
+class HideLoadMoreButtonPatch : BytecodePatch(listOf(HideLoadMoreButtonFingerprint)) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ HideLoadMoreButtonFingerprint.result?.let {
+ it.mutableMethod.apply {
+ val moveRegisterIndex = it.scanResult.patternScanResult!!.endIndex
+ val viewRegister = instruction(moveRegisterIndex).registerA
+
+ val insertIndex = moveRegisterIndex + 1
+ addInstruction(
+ insertIndex,
+ "invoke-static { v$viewRegister }, " +
+ "$INTEGRATIONS_CLASS_DESCRIPTOR->hideLoadMoreButton(Landroid/view/View;)V"
+ )
+ }
+ } ?: return HideLoadMoreButtonFingerprint.toErrorResult()
+
+ return PatchResultSuccess()
+ }
+
+ private companion object {
+ const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/HideLoadMoreButtonPatch;"
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/resource/patch/HideLoadMoreButtonResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/resource/patch/HideLoadMoreButtonResourcePatch.kt
new file mode 100644
index 000000000..0638a12dd
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/resource/patch/HideLoadMoreButtonResourcePatch.kt
@@ -0,0 +1,39 @@
+package app.revanced.patches.youtube.layout.hide.loadmorebutton.resource.patch
+
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.data.ResourceContext
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.ResourcePatch
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patches.shared.settings.preference.impl.StringResource
+import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
+import app.revanced.patches.youtube.layout.hide.loadmorebutton.annotations.HideLoadMoreButtonCompatibility
+import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+
+@Name("hide-load-more-button-resource-patch")
+@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
+@HideLoadMoreButtonCompatibility
+class HideLoadMoreButtonResourcePatch : ResourcePatch {
+ override fun execute(context: ResourceContext): PatchResult {
+ SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
+ SwitchPreference(
+ "revanced_hide_load_more_button",
+ StringResource("revanced_hide_load_more_button_title", "Hide Load More button"),
+ StringResource("revanced_hide_load_more_button_summary_on", "Load More button is hidden"),
+ StringResource("revanced_hide_load_more_button_summary_off", "Load More button is shown")
+ )
+ )
+
+ expandButtonDownId = ResourceMappingPatch.resourceMappings.single {
+ it.type == "layout" && it.name == "expand_button_down"
+ }.id
+
+ return PatchResultSuccess()
+ }
+
+ internal companion object {
+ var expandButtonDownId: Long = -1
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/annotations/HideEmailAddressCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/annotations/HideEmailAddressCompatibility.kt
index a353abda9..27abf2723 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/annotations/HideEmailAddressCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/annotations/HideEmailAddressCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.personalinformation.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideEmailAddressCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/bytecode/fingerprints/AccountSwitcherAccessibilityLabelFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/bytecode/fingerprints/AccountSwitcherAccessibilityLabelFingerprint.kt
index 5e5d9fb23..4597c4da4 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/bytecode/fingerprints/AccountSwitcherAccessibilityLabelFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/bytecode/fingerprints/AccountSwitcherAccessibilityLabelFingerprint.kt
@@ -15,7 +15,7 @@ object AccountSwitcherAccessibilityLabelFingerprint : MethodFingerprint(
Opcode.APUT_OBJECT,
Opcode.CONST,
),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.implementation?.instructions?.any { instruction ->
instruction.opcode.ordinal == Opcode.CONST.ordinal &&
(instruction as? WideLiteralInstruction)?.wideLiteral == HideEmailAddressResourcePatch.accountSwitcherAccessibilityLabelId
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/bytecode/patch/HideEmailAddressPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/bytecode/patch/HideEmailAddressPatch.kt
index a6f443d7d..79d0e8542 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/bytecode/patch/HideEmailAddressPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/bytecode/patch/HideEmailAddressPatch.kt
@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.layout.hide.personalinformation.bytecode.patch
+import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
@@ -29,23 +30,22 @@ class HideEmailAddressPatch : BytecodePatch(
)
) {
override fun execute(context: BytecodeContext): PatchResult {
- val accountSwitcherAccessibilityLabelResult = AccountSwitcherAccessibilityLabelFingerprint.result!!
- val accountSwitcherAccessibilityLabelMethod = accountSwitcherAccessibilityLabelResult.mutableMethod
+ AccountSwitcherAccessibilityLabelFingerprint.result?.let {
+ it.mutableMethod.apply {
+ val setVisibilityConstIndex = it.scanResult.patternScanResult!!.endIndex
- val setVisibilityConstIndex =
- accountSwitcherAccessibilityLabelResult.scanResult.patternScanResult!!.endIndex
+ val setVisibilityConstRegister =
+ instruction(setVisibilityConstIndex - 2).registerA
- val setVisibilityConstRegister = (
- accountSwitcherAccessibilityLabelMethod.instruction
- (setVisibilityConstIndex - 2) as OneRegisterInstruction
- ).registerA
-
- accountSwitcherAccessibilityLabelMethod.addInstructions(
- setVisibilityConstIndex, """
- invoke-static {v$setVisibilityConstRegister}, Lapp/revanced/integrations/patches/HideEmailAddressPatch;->hideEmailAddress(I)I
- move-result v$setVisibilityConstRegister
- """
- )
+ addInstructions(
+ setVisibilityConstIndex,
+ """
+ invoke-static {v$setVisibilityConstRegister}, Lapp/revanced/integrations/patches/HideEmailAddressPatch;->hideEmailAddress(I)I
+ move-result v$setVisibilityConstRegister
+ """
+ )
+ }
+ } ?: return AccountSwitcherAccessibilityLabelFingerprint.toErrorResult()
return PatchResultSuccess()
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/resource/patch/HideEmailAddressResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/resource/patch/HideEmailAddressResourcePatch.kt
index 044c3475f..8d7859393 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/resource/patch/HideEmailAddressResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/personalinformation/resource/patch/HideEmailAddressResourcePatch.kt
@@ -27,7 +27,6 @@ class HideEmailAddressResourcePatch : ResourcePatch {
SwitchPreference(
"revanced_hide_email_address",
StringResource("revanced_hide_email_address_title", "Hide email in account switcher"),
- false,
StringResource("revanced_hide_email_address_summary_on", "Email address is hidden"),
StringResource("revanced_hide_email_address_summary_off", "Email address is shown")
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/overlay/bytecode/fingerprints/CreatePlayerOverviewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/overlay/bytecode/fingerprints/CreatePlayerOverviewFingerprint.kt
new file mode 100644
index 000000000..f235b62ec
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/overlay/bytecode/fingerprints/CreatePlayerOverviewFingerprint.kt
@@ -0,0 +1,28 @@
+package app.revanced.patches.youtube.layout.hide.player.overlay.bytecode.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import app.revanced.patches.youtube.layout.hide.player.overlay.resource.patch.HidePlayerOverlayResourcePatch
+import org.jf.dexlib2.AccessFlags
+import org.jf.dexlib2.Opcode
+import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
+
+object CreatePlayerOverviewFingerprint : MethodFingerprint(
+ returnType = "V",
+ accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
+ opcodes = listOf(
+ Opcode.CONST,
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.MOVE_RESULT_OBJECT,
+ Opcode.CHECK_CAST
+ ),
+ customFingerprint = { methodDef, _ ->
+ methodDef.implementation?.instructions?.any {
+ if (it.opcode != Opcode.CONST) return@any false
+
+ val literal = (it as WideLiteralInstruction).wideLiteral
+
+ literal == HidePlayerOverlayResourcePatch.scrimOverlayId
+ } ?: false
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/overlay/bytecode/patch/HidePlayerOverlayPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/overlay/bytecode/patch/HidePlayerOverlayPatch.kt
new file mode 100644
index 000000000..d5b7bd9f4
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/overlay/bytecode/patch/HidePlayerOverlayPatch.kt
@@ -0,0 +1,53 @@
+package app.revanced.patches.youtube.layout.hide.player.overlay.bytecode.patch
+
+import app.revanced.extensions.toErrorResult
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.addInstruction
+import app.revanced.patcher.extensions.instruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patches.youtube.layout.hide.player.overlay.annotations.HidePlayerOverlayPatchCompatibility
+import app.revanced.patches.youtube.layout.hide.player.overlay.bytecode.fingerprints.CreatePlayerOverviewFingerprint
+import app.revanced.patches.youtube.layout.hide.player.overlay.resource.patch.HidePlayerOverlayResourcePatch
+import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
+import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
+
+@Patch
+@Name("hide-player-overlay")
+@Description("Hides the dark background overlay from the player when player controls are visible.")
+@DependsOn([HidePlayerOverlayResourcePatch::class])
+@HidePlayerOverlayPatchCompatibility
+@Version("0.0.2")
+class HidePlayerOverlayPatch : BytecodePatch(listOf(CreatePlayerOverviewFingerprint)) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ CreatePlayerOverviewFingerprint.result?.let { result ->
+ result.mutableMethod.apply {
+ val viewRegisterIndex = implementation!!.instructions.indexOfFirst {
+ val literal = (it as? WideLiteralInstruction)?.wideLiteral
+
+ literal == HidePlayerOverlayResourcePatch.scrimOverlayId
+ } + 3
+ val viewRegister = instruction(viewRegisterIndex).registerA
+
+ val insertIndex = viewRegisterIndex + 1
+ addInstruction(
+ insertIndex,
+ "invoke-static { v$viewRegister }, " +
+ "$INTEGRATIONS_CLASS_DESCRIPTOR->hidePlayerOverlay(Landroid/widget/ImageView;)V"
+ )
+ }
+ } ?: return CreatePlayerOverviewFingerprint.toErrorResult()
+
+ return PatchResultSuccess()
+ }
+
+ private companion object {
+ const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/HidePlayerOverlayPatch;"
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/overlay/patch/HidePlayerOverlayPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/overlay/patch/HidePlayerOverlayPatch.kt
deleted file mode 100644
index 060073e40..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/overlay/patch/HidePlayerOverlayPatch.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.player.overlay.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.annotation.Version
-import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.PatchResult
-import app.revanced.patcher.patch.PatchResultSuccess
-import app.revanced.patcher.patch.ResourcePatch
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.layout.hide.player.overlay.annotations.HidePlayerOverlayPatchCompatibility
-
-@Patch(false)
-@Name("hide-player-overlay")
-@Description("Hides the dark player overlay when player controls are visible.")
-@HidePlayerOverlayPatchCompatibility
-@Version("0.0.1")
-class HidePlayerOverlayPatch : ResourcePatch {
- override fun execute(context: ResourceContext): PatchResult {
- val attributes = arrayOf("height", "width")
-
- context.xmlEditor[RESOURCE_FILE_PATH].use { editor ->
- editor.file.getElementsByTagName("FrameLayout").item(0).childNodes.apply {
- for (i in 1 until length) {
- val view = item(i)
- if (
- view.attributes.getNamedItem("android:id")
- ?.nodeValue
- ?.endsWith("scrim_overlay") == true
- ) {
- attributes.forEach {
- view.attributes.getNamedItem("android:layout_$it").nodeValue = "0.0dip"
- }
- break
- }
- }
- }
- }
-
- return PatchResultSuccess()
- }
-
- private companion object {
- const val RESOURCE_FILE_PATH = "res/layout/youtube_controls_overlay.xml"
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/overlay/resource/patch/HidePlayerOverlayResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/overlay/resource/patch/HidePlayerOverlayResourcePatch.kt
new file mode 100644
index 000000000..7907f2225
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/overlay/resource/patch/HidePlayerOverlayResourcePatch.kt
@@ -0,0 +1,39 @@
+package app.revanced.patches.youtube.layout.hide.player.overlay.resource.patch
+
+import app.revanced.patcher.data.ResourceContext
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.ResourcePatch
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patches.shared.settings.preference.impl.StringResource
+import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
+import app.revanced.patches.youtube.layout.hide.player.overlay.annotations.HidePlayerOverlayPatchCompatibility
+import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import jdk.jfr.Name
+
+@Name("hide-player-overlay-resource-patch")
+@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
+@HidePlayerOverlayPatchCompatibility
+class HidePlayerOverlayResourcePatch : ResourcePatch {
+ override fun execute(context: ResourceContext): PatchResult {
+ SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
+ SwitchPreference(
+ "revanced_hide_player_overlay",
+ StringResource("revanced_hide_player_overlay_title", "Hide background overlay in player"),
+ StringResource("revanced_hide_player_overlay_summary_on", "Background overlay is hidden"),
+ StringResource("revanced_hide_player_overlay_summary_off", "Background overlay is shown")
+ )
+ )
+
+ scrimOverlayId = ResourceMappingPatch.resourceMappings.single {
+ it.type == "id" && it.name == "scrim_overlay"
+ }.id
+
+ return PatchResultSuccess()
+ }
+
+ internal companion object {
+ var scrimOverlayId: Long = -1
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/annotations/HideSeekbarCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/annotations/HideSeekbarCompatibility.kt
index aa4639f9e..560e17a8e 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/annotations/HideSeekbarCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/annotations/HideSeekbarCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.seekbar.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideSeekbarCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/patch/HideSeekbarPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/patch/HideSeekbarPatch.kt
index 6fdfa4b84..08102a5c4 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/patch/HideSeekbarPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/patch/HideSeekbarPatch.kt
@@ -16,11 +16,16 @@ import app.revanced.patches.shared.fingerprints.SeekbarOnDrawFingerprint
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.layout.hide.seekbar.annotations.HideSeekbarCompatibility
+import app.revanced.patches.youtube.layout.seekbar.bytecode.patch.SeekbarColorBytecodePatch
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
+@DependsOn([
+ IntegrationsPatch::class,
+ SettingsPatch::class,
+ SeekbarColorBytecodePatch::class // Used to hide the seekbar in the feed and watch history
+])
@Name("hide-seekbar")
@Description("Hides the seekbar.")
@HideSeekbarCompatibility
@@ -33,7 +38,6 @@ class HideSeekbarPatch : BytecodePatch(
SwitchPreference(
"revanced_hide_seekbar",
StringResource("revanced_hide_seekbar_title", "Hide seekbar"),
- false,
StringResource("revanced_hide_seekbar_summary_on", "Seekbar is hidden"),
StringResource("revanced_hide_seekbar_summary_off", "Seekbar is shown")
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/annotations/HideShortsComponentsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/annotations/HideShortsComponentsCompatibility.kt
new file mode 100644
index 000000000..a058e84cd
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/annotations/HideShortsComponentsCompatibility.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.youtube.layout.hide.shorts.annotations
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
+@Target(AnnotationTarget.CLASS)
+internal annotation class HideShortsComponentsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/BottomNavigationBarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/BottomNavigationBarFingerprint.kt
new file mode 100644
index 000000000..c53e79673
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/BottomNavigationBarFingerprint.kt
@@ -0,0 +1,18 @@
+package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import org.jf.dexlib2.Opcode
+
+object BottomNavigationBarFingerprint : MethodFingerprint(
+ opcodes = listOf(
+ Opcode.MOVE_RESULT_OBJECT, // Refers to bottom navigation bar
+ Opcode.IF_EQZ,
+ Opcode.IGET_OBJECT,
+ Opcode.IGET_OBJECT,
+ Opcode.IGET_OBJECT,
+ ),
+ strings = listOf(
+ "navigation_endpoint_interaction_logging_extension",
+ "reel_watch_fragment_watch_while",
+ ),
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/CreateShortsButtonsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/CreateShortsButtonsFingerprint.kt
new file mode 100644
index 000000000..2f99a2f0b
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/CreateShortsButtonsFingerprint.kt
@@ -0,0 +1,19 @@
+package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import app.revanced.patches.youtube.layout.hide.shorts.resource.patch.HideShortsComponentsResourcePatch
+import org.jf.dexlib2.Opcode
+import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
+
+object CreateShortsButtonsFingerprint : MethodFingerprint(
+ parameters = listOf("Z", "Z", "L"),
+ customFingerprint = { methodDef, _ ->
+ methodDef.implementation?.instructions?.any {
+ if (it.opcode != Opcode.CONST) return@any false
+
+ val literal = (it as WideLiteralInstruction).wideLiteral
+
+ literal == HideShortsComponentsResourcePatch.reelPlayerRightLargeIconSize
+ } ?: false
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/ReelConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/ReelConstructorFingerprint.kt
new file mode 100644
index 000000000..2d6836b2f
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/ReelConstructorFingerprint.kt
@@ -0,0 +1,19 @@
+package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import app.revanced.patches.youtube.layout.hide.shorts.resource.patch.HideShortsComponentsResourcePatch
+import org.jf.dexlib2.Opcode
+import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
+
+object ReelConstructorFingerprint : MethodFingerprint(
+ opcodes = listOf(Opcode.INVOKE_VIRTUAL),
+ customFingerprint = { method, _ ->
+ method.implementation?.instructions?.any {
+ if (it.opcode != Opcode.CONST) return@any false
+
+ val literal = (it as WideLiteralInstruction).wideLiteral
+
+ literal == HideShortsComponentsResourcePatch.reelMultipleItemShelfId
+ } ?: false
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/RenderBottomNavigationBarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/RenderBottomNavigationBarFingerprint.kt
new file mode 100644
index 000000000..216d7276a
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/RenderBottomNavigationBarFingerprint.kt
@@ -0,0 +1,19 @@
+package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import org.jf.dexlib2.Opcode
+
+object RenderBottomNavigationBarFingerprint : MethodFingerprint(
+ opcodes = listOf(
+ Opcode.IGET_OBJECT,
+ Opcode.MONITOR_ENTER,
+ Opcode.IGET_OBJECT,
+ Opcode.IF_EQZ,
+ Opcode.INVOKE_INTERFACE,
+ Opcode.MONITOR_EXIT,
+ Opcode.RETURN_VOID,
+ Opcode.MOVE_EXCEPTION,
+ Opcode.MONITOR_EXIT,
+ Opcode.THROW,
+ )
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/RenderBottomNavigationBarParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/RenderBottomNavigationBarParentFingerprint.kt
new file mode 100644
index 000000000..70a2ebc0a
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/RenderBottomNavigationBarParentFingerprint.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+
+object RenderBottomNavigationBarParentFingerprint : MethodFingerprint(
+ parameters = listOf("I", "I", "L", "L", "J", "L"),
+ strings = listOf("aa")
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/SetPivotBarVisibilityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/SetPivotBarVisibilityFingerprint.kt
new file mode 100644
index 000000000..6c169f2ae
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/SetPivotBarVisibilityFingerprint.kt
@@ -0,0 +1,19 @@
+package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import org.jf.dexlib2.Opcode
+
+object SetPivotBarVisibilityFingerprint : MethodFingerprint(
+ parameters = listOf("Z"),
+ opcodes = listOf(
+ Opcode.IGET_OBJECT,
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.MOVE_RESULT,
+ Opcode.IF_EQZ,
+ Opcode.RETURN_VOID,
+ Opcode.IGET_OBJECT,
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.MOVE_RESULT_OBJECT,
+ Opcode.CHECK_CAST,
+ )
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/SetPivotBarVisibilityParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/SetPivotBarVisibilityParentFingerprint.kt
new file mode 100644
index 000000000..170569b9a
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/fingerprints/SetPivotBarVisibilityParentFingerprint.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+
+object SetPivotBarVisibilityParentFingerprint : MethodFingerprint(
+ parameters = listOf("Z"),
+ strings = listOf("FEnotifications_inbox")
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/patch/HideShortsComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/patch/HideShortsComponentsPatch.kt
new file mode 100644
index 000000000..dcad8f43a
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/bytecode/patch/HideShortsComponentsPatch.kt
@@ -0,0 +1,146 @@
+package app.revanced.patches.youtube.layout.hide.shorts.bytecode.patch
+
+import app.revanced.extensions.findIndexForIdResource
+import app.revanced.extensions.injectHideViewCall
+import app.revanced.extensions.toErrorResult
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.addInstruction
+import app.revanced.patcher.extensions.instruction
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
+import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patches.youtube.layout.hide.shorts.annotations.HideShortsComponentsCompatibility
+import app.revanced.patches.youtube.layout.hide.shorts.bytecode.fingerprints.*
+import app.revanced.patches.youtube.layout.hide.shorts.resource.patch.HideShortsComponentsResourcePatch
+import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
+import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
+import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
+import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
+import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
+
+@Patch
+@DependsOn(
+ [
+ IntegrationsPatch::class,
+ LithoFilterPatch::class,
+ HideShortsComponentsResourcePatch::class,
+ ResourceMappingPatch::class
+ ]
+)
+@Name("hide-shorts-components")
+@Description("Hides components from YouTube Shorts.")
+@HideShortsComponentsCompatibility
+@Version("0.0.1")
+class HideShortsComponentsPatch : BytecodePatch(
+ listOf(
+ CreateShortsButtonsFingerprint,
+ ReelConstructorFingerprint,
+ BottomNavigationBarFingerprint,
+ RenderBottomNavigationBarParentFingerprint,
+ SetPivotBarVisibilityParentFingerprint
+ )
+) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ // region Hide the Shorts shelf.
+
+ ReelConstructorFingerprint.result?.let {
+ it.mutableMethod.apply {
+ val insertIndex = it.scanResult.patternScanResult!!.startIndex + 2
+ val viewRegister = instruction(insertIndex).registerA
+
+ injectHideViewCall(
+ insertIndex,
+ viewRegister,
+ CLASS_DESCRIPTOR,
+ "hideShortsShelf"
+ )
+ }
+ } ?: return ReelConstructorFingerprint.toErrorResult()
+
+ // endregion
+
+ // region Hide the Shorts buttons.
+
+ // Some Shorts buttons are views, hide them by setting their visibility to GONE.
+ CreateShortsButtonsFingerprint.result?.let {
+ ShortsButtons.values().forEach { button -> button.injectHideCall(it.mutableMethod) }
+ } ?: return CreateShortsButtonsFingerprint.toErrorResult()
+
+ // endregion
+
+ // region Hide the navigation bar.
+
+ // Hook to get the pivotBar view.
+ SetPivotBarVisibilityParentFingerprint.result?.let {
+ if (!SetPivotBarVisibilityFingerprint.resolve(context, it.classDef))
+ throw SetPivotBarVisibilityFingerprint.toErrorResult()
+
+ SetPivotBarVisibilityFingerprint.result!!.let { result ->
+ result.mutableMethod.apply {
+ val checkCastIndex = result.scanResult.patternScanResult!!.endIndex
+ val viewRegister = instruction(checkCastIndex).registerA
+ addInstruction(
+ checkCastIndex + 1,
+ "sput-object v$viewRegister, $CLASS_DESCRIPTOR->pivotBar:" +
+ "Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;"
+ )
+ }
+ }
+ } ?: return SetPivotBarVisibilityParentFingerprint.toErrorResult()
+
+ // Hook to hide the navigation bar when Shorts are being played.
+ RenderBottomNavigationBarParentFingerprint.result?.let {
+ if (!RenderBottomNavigationBarFingerprint.resolve(context, it.classDef))
+ throw RenderBottomNavigationBarFingerprint.toErrorResult()
+
+ RenderBottomNavigationBarFingerprint.result!!.mutableMethod.apply {
+ addInstruction(0, "invoke-static { }, $CLASS_DESCRIPTOR->hideNavigationBar()V")
+ }
+ } ?: return RenderBottomNavigationBarParentFingerprint.toErrorResult()
+
+ // Required to prevent a black bar from appearing at the bottom of the screen.
+ BottomNavigationBarFingerprint.result?.let {
+ it.mutableMethod.apply {
+ val moveResultIndex = it.scanResult.patternScanResult!!.startIndex
+ val viewRegister = instruction(moveResultIndex).registerA
+ val insertIndex = moveResultIndex + 1
+
+ addInstruction(
+ insertIndex,
+ "invoke-static { v$viewRegister }, $CLASS_DESCRIPTOR->" +
+ "hideNavigationBar(Landroid/view/View;)Landroid/view/View;"
+ )
+ }
+ } ?: return BottomNavigationBarFingerprint.toErrorResult()
+
+ // endregion
+
+ return PatchResultSuccess()
+ }
+
+ private companion object {
+ private const val CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/ShortsFilter;"
+
+ private enum class ShortsButtons(private val resourceName: String, private val methodName: String) {
+ COMMENTS("reel_dyn_comment", "hideShortsCommentsButton"),
+ REMIX("reel_dyn_remix", "hideShortsRemixButton"),
+ SHARE("reel_dyn_share", "hideShortsShareButton");
+
+ fun injectHideCall(method: MutableMethod) {
+ val referencedIndex = method.findIndexForIdResource(resourceName)
+
+ val setIdIndex = referencedIndex + 1
+ val viewRegister = method.instruction(setIdIndex).registerC
+ method.injectHideViewCall(setIdIndex, viewRegister, CLASS_DESCRIPTOR, methodName)
+ }
+ }
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/resource/patch/HideShortsComponentsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/resource/patch/HideShortsComponentsResourcePatch.kt
new file mode 100644
index 000000000..29e3d149e
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/resource/patch/HideShortsComponentsResourcePatch.kt
@@ -0,0 +1,89 @@
+package app.revanced.patches.youtube.layout.hide.shorts.resource.patch
+
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.ResourceContext
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.ResourcePatch
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
+import app.revanced.patches.shared.settings.preference.impl.StringResource
+import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
+import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+
+@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
+@Version("0.0.1")
+class HideShortsComponentsResourcePatch : ResourcePatch {
+ override fun execute(context: ResourceContext): PatchResult {
+ SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
+ PreferenceScreen(
+ "revanced_shorts",
+ StringResource("revanced_shorts_title", "Shorts components"),
+ listOf(
+ SwitchPreference(
+ "revanced_hide_shorts",
+ StringResource("revanced_hide_shorts_enabled_title", "Hide shorts"),
+ StringResource("revanced_hide_shorts_on", "Shorts are hidden"),
+ StringResource("revanced_hide_shorts_off", "Shorts are shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_shorts_join_button",
+ StringResource("revanced_hide_shorts_join_button_title", "Hide join button"),
+ StringResource("revanced_hide_shorts_join_button_on", "Join button is hidden"),
+ StringResource("revanced_hide_shorts_join_button_off", "Join button is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_shorts_subscribe_button",
+ StringResource("revanced_hide_shorts_subscribe_button_title", "Hide subscribe button"),
+ StringResource("revanced_hide_shorts_subscribe_button_on", "Subscribe button is hidden"),
+ StringResource("revanced_hide_shorts_subscribe_button_off", "Subscribe button is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_shorts_thanks_button",
+ StringResource("revanced_hide_shorts_thanks_button_title", "Hide thanks button"),
+ StringResource("revanced_hide_shorts_thanks_button_on", "Thanks button is hidden"),
+ StringResource("revanced_hide_shorts_thanks_button_off", "Thanks button is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_shorts_comments_button",
+ StringResource("revanced_hide_shorts_comments_button_title", "Hide comments button"),
+ StringResource("revanced_hide_shorts_comments_button_on", "Comments button is hidden"),
+ StringResource("revanced_hide_shorts_comments_button_off", "Comments button is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_shorts_remix_button",
+ StringResource("revanced_hide_shorts_remix_button_title", "Hide remix button"),
+ StringResource("revanced_hide_shorts_remix_button_on", "Remix button is hidden"),
+ StringResource("revanced_hide_shorts_remix_button_off", "Remix button is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_shorts_share_button",
+ StringResource("revanced_hide_shorts_share_button_title", "Hide share button"),
+ StringResource("revanced_hide_shorts_share_button_on", "Share button is hidden"),
+ StringResource("revanced_hide_shorts_share_button_off", "Share button is shown")
+ ),
+ SwitchPreference(
+ "revanced_hide_shorts_navigation_bar",
+ StringResource("revanced_hide_shorts_navigation_bar_title", "Hide navigation bar"),
+ StringResource("revanced_hide_shorts_navigation_bar_on", "Navigation bar is hidden"),
+ StringResource("revanced_hide_shorts_navigation_bar_off", "Navigation bar is shown")
+ ),
+ ),
+ StringResource("revanced_shorts_summary", "Manage the visibility of Shorts components")
+ )
+ )
+
+ fun String.getId() = ResourceMappingPatch.resourceMappings.single { it.name == this }.id
+
+ reelMultipleItemShelfId = "reel_multiple_items_shelf".getId()
+ reelPlayerRightLargeIconSize = "reel_player_right_large_icon_size".getId()
+
+ return PatchResultSuccess()
+ }
+
+ companion object {
+ var reelMultipleItemShelfId: Long = -1
+ var reelPlayerRightLargeIconSize = -1L
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/annotations/HideTimeCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/annotations/HideTimeCompatibility.kt
index 765783005..c3f3c7776 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/annotations/HideTimeCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/annotations/HideTimeCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.hide.time.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class HideTimeCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/patch/HideTimestampPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/patch/HideTimestampPatch.kt
index e30f8cb5a..635578a64 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/patch/HideTimestampPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/patch/HideTimestampPatch.kt
@@ -33,7 +33,6 @@ class HideTimestampPatch : BytecodePatch(
SwitchPreference(
"revanced_hide_timestamp",
StringResource("revanced_hide_timestamp_title", "Hide video timestamp"),
- false,
StringResource("revanced_hide_timestamp_summary_on", "Timestamp is hidden"),
StringResource("revanced_hide_timestamp_summary_off", "Timestamp is shown")
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watchinvr/annotations/WatchInVRCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watchinvr/annotations/WatchInVRCompatibility.kt
new file mode 100644
index 000000000..9eba5cc7c
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watchinvr/annotations/WatchInVRCompatibility.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.youtube.layout.hide.watchinvr.annotations
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
+@Target(AnnotationTarget.CLASS)
+internal annotation class WatchInVRCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watchinvr/annotations/WatchinVRCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watchinvr/annotations/WatchinVRCompatibility.kt
deleted file mode 100644
index b810666de..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watchinvr/annotations/WatchinVRCompatibility.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.watchinvr.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class WatchinVRCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watchinvr/patch/WatchInVRPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watchinvr/patch/WatchInVRPatch.kt
index 84e8d8d94..89b278620 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watchinvr/patch/WatchInVRPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watchinvr/patch/WatchInVRPatch.kt
@@ -12,7 +12,7 @@ import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
-import app.revanced.patches.youtube.layout.hide.watchinvr.annotations.WatchinVRCompatibility
+import app.revanced.patches.youtube.layout.hide.watchinvr.annotations.WatchInVRCompatibility
import app.revanced.patches.youtube.layout.hide.watchinvr.fingerprints.WatchInVRFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
@@ -21,7 +21,7 @@ import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
@Name("hide-watch-in-vr")
@Description("Hides the option to watch in VR from the player settings flyout panel.")
-@WatchinVRCompatibility
+@WatchInVRCompatibility
@Version("0.0.1")
class WatchInVRPatch : BytecodePatch(
listOf(
@@ -33,7 +33,6 @@ class WatchInVRPatch : BytecodePatch(
SwitchPreference(
"revanced_hide_watch_in_vr",
StringResource("revanced_hide_watch_in_vr_title", "Hide VR setting"),
- false,
StringResource("revanced_hide_watch_in_vr_summary_on", "VR setting is hidden"),
StringResource("revanced_hide_watch_in_vr_summary_off", "VR setting is shown")
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/annotations/HideWatermarkCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/annotations/HideWatermarkCompatibility.kt
new file mode 100644
index 000000000..8d11da21a
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/annotations/HideWatermarkCompatibility.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.youtube.layout.hide.watermark.annotations
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
+@Target(AnnotationTarget.CLASS)
+internal annotation class HideWatermarkCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/annotations/HideWaterwarkCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/annotations/HideWaterwarkCompatibility.kt
deleted file mode 100644
index fd691647d..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/annotations/HideWaterwarkCompatibility.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package app.revanced.patches.youtube.layout.hide.watermark.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class HideWatermarkCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/patch/HideWatermarkPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/patch/HideWatermarkPatch.kt
index f149f3cf6..c6c2b3b06 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/patch/HideWatermarkPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/watermark/patch/HideWatermarkPatch.kt
@@ -37,7 +37,6 @@ class HideWatermarkPatch : BytecodePatch(
SwitchPreference(
"revanced_hide_video_watermark",
StringResource("revanced_hide_video_watermark_title", "Hide creator watermark on videos"),
- true,
StringResource("revanced_hide_video_watermark_summary_on", "Watermark is hidden"),
StringResource("revanced_hide_video_watermark_summary_off", "Watermark is shown")
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/annotations/OldQualityLayoutCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/annotations/OldQualityLayoutCompatibility.kt
deleted file mode 100644
index 542e4b32f..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/annotations/OldQualityLayoutCompatibility.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package app.revanced.patches.youtube.layout.oldqualitylayout.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class OldQualityLayoutCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/fingerprints/QualityMenuViewInflateFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/fingerprints/QualityMenuViewInflateFingerprint.kt
deleted file mode 100644
index 4abb688e9..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/fingerprints/QualityMenuViewInflateFingerprint.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package app.revanced.patches.youtube.layout.oldqualitylayout.fingerprints
-
-import app.revanced.patcher.extensions.or
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import org.jf.dexlib2.AccessFlags
-import org.jf.dexlib2.Opcode
-
-object QualityMenuViewInflateFingerprint : MethodFingerprint(
- "L", AccessFlags.FINAL or AccessFlags.PUBLIC, listOf("L", "L", "L"), listOf(
- Opcode.INVOKE_SUPER,
- Opcode.CONST,
- Opcode.CONST_4,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.CONST,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.CONST_16,
- Opcode.INVOKE_VIRTUAL,
- Opcode.CONST,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.CHECK_CAST,
- Opcode.CONST,
- Opcode.INVOKE_VIRTUAL,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.IGET_OBJECT,
- Opcode.IGET_OBJECT,
- Opcode.CONST_STRING,
- )
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/fullscreen/remove/annotations/FullscreenPanelsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/panels/fullscreen/remove/annotations/FullscreenPanelsCompatibility.kt
index 24b1ca363..86a2865c2 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/fullscreen/remove/annotations/FullscreenPanelsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/panels/fullscreen/remove/annotations/FullscreenPanelsCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.panels.fullscreen.remove.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class FullscreenPanelsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/fullscreen/remove/fingerprints/FullscreenViewAdderParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/panels/fullscreen/remove/fingerprints/FullscreenViewAdderParentFingerprint.kt
index 6184eb0c2..601e62b83 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/fullscreen/remove/fingerprints/FullscreenViewAdderParentFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/panels/fullscreen/remove/fingerprints/FullscreenViewAdderParentFingerprint.kt
@@ -14,5 +14,7 @@ object FullscreenViewAdderParentFingerprint : MethodFingerprint(
Opcode.CONST_4,
Opcode.INVOKE_VIRTUAL,
),
- customFingerprint = { it.definingClass.endsWith("FullscreenEngagementPanelOverlay;") }
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass.endsWith("FullscreenEngagementPanelOverlay;")
+ }
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/fullscreen/remove/patch/FullscreenPanelsRemoverPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/panels/fullscreen/remove/patch/FullscreenPanelsRemoverPatch.kt
index 3939bdcac..791273ad6 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/fullscreen/remove/patch/FullscreenPanelsRemoverPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/panels/fullscreen/remove/patch/FullscreenPanelsRemoverPatch.kt
@@ -37,7 +37,6 @@ class FullscreenPanelsRemoverPatch : BytecodePatch(
SwitchPreference(
"revanced_hide_fullscreen_panels",
StringResource("revanced_hide_fullscreen_panels_title", "Hide fullscreen panels"),
- true,
StringResource("revanced_hide_fullscreen_panels_summary_on", "Fullscreen panels are hidden"),
StringResource("revanced_hide_fullscreen_panels_summary_off", "Fullscreen panels are shown")
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/annotations/PlayerPopupPanelsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/annotations/PlayerPopupPanelsCompatibility.kt
index c37a86b5f..c05d454b4 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/annotations/PlayerPopupPanelsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/annotations/PlayerPopupPanelsCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.panels.popup.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class PlayerPopupPanelsCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/fingerprints/EngagementPanelControllerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/fingerprints/EngagementPanelControllerFingerprint.kt
index c09853574..a45ae6093 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/fingerprints/EngagementPanelControllerFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/fingerprints/EngagementPanelControllerFingerprint.kt
@@ -9,7 +9,7 @@ import org.jf.dexlib2.AccessFlags
@FuzzyPatternScanMethod(3)
object EngagementPanelControllerFingerprint : MethodFingerprint(
returnType = "L",
- access = AccessFlags.PRIVATE or AccessFlags.FINAL,
+ accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
strings = listOf(
"EngagementPanelController: cannot show EngagementPanel before EngagementPanelController.init() has been called.",
"[EngagementPanel] Cannot show EngagementPanel before EngagementPanelController.init() has been called."
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/patch/PlayerPopupPanelsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/patch/PlayerPopupPanelsPatch.kt
index a8dabc9ca..bf2447c4e 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/patch/PlayerPopupPanelsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/patch/PlayerPopupPanelsPatch.kt
@@ -32,11 +32,10 @@ class PlayerPopupPanelsPatch : BytecodePatch(
override fun execute(context: BytecodeContext): PatchResult {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
SwitchPreference(
- "revanced_player_popup_panels_enabled",
- StringResource("revanced_player_popup_panels_title", "Disable player popup panels"),
- false,
- StringResource("revanced_player_popup_panels_summary_on", "Player popup panels are disabled"),
- StringResource("revanced_player_popup_panels_summary_off", "Player popup panels are enabled")
+ "revanced_hide_player_popup_panels",
+ StringResource("revanced_hide_player_popup_panels_title", "Hide player popup panels"),
+ StringResource("revanced_hide_player_popup_panels_summary_on", "Player popup panels are hidden"),
+ StringResource("revanced_hide_player_popup_panels_summary_off", "Player popup panels are shown")
)
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/annotations/ReturnYouTubeDislikeCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/annotations/ReturnYouTubeDislikeCompatibility.kt
index 747d0a947..aa0f3fcc5 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/annotations/ReturnYouTubeDislikeCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/annotations/ReturnYouTubeDislikeCompatibility.kt
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.returnyoutubedislike.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.15.40", "18.16.37"))])
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class ReturnYouTubeDislikeCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/DislikesOldLayoutTextViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/DislikesOldLayoutTextViewFingerprint.kt
index 29ab1564d..7fe768162 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/DislikesOldLayoutTextViewFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/DislikesOldLayoutTextViewFingerprint.kt
@@ -10,7 +10,7 @@ import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
object DislikesOldLayoutTextViewFingerprint : MethodFingerprint(
returnType = "V",
parameters = listOf("L"),
- access = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
opcodes = listOf(
Opcode.CONST, // resource identifier register
Opcode.INVOKE_VIRTUAL,
@@ -19,7 +19,7 @@ object DislikesOldLayoutTextViewFingerprint : MethodFingerprint(
Opcode.IF_NEZ, // textview register
Opcode.GOTO,
),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.implementation?.instructions?.any { instruction ->
instruction.opcode.ordinal == Opcode.CONST.ordinal &&
(instruction as? WideLiteralInstruction)?.wideLiteral == ReturnYouTubeDislikeResourcePatch.oldUIDislikeId
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/ShortsTextComponentParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/ShortsTextComponentParentFingerprint.kt
deleted file mode 100644
index f4e6f7801..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/ShortsTextComponentParentFingerprint.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
-
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import org.jf.dexlib2.Opcode
-
-object ShortsTextComponentParentFingerprint : MethodFingerprint(
- returnType = "V",
- parameters = listOf("L", "L"),
- opcodes = listOf(
- Opcode.INVOKE_STATIC,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.GOTO,
- Opcode.INVOKE_STATIC,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.INVOKE_VIRTUAL,
- Opcode.RETURN_VOID,
- Opcode.IGET_OBJECT,
- Opcode.CHECK_CAST,
- Opcode.IGET_BOOLEAN,
- Opcode.IF_EQZ,
- Opcode.INVOKE_STATIC
- )
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/ShortsTextViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/ShortsTextViewFingerprint.kt
new file mode 100644
index 000000000..9d5c2ec2a
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/ShortsTextViewFingerprint.kt
@@ -0,0 +1,30 @@
+package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import org.jf.dexlib2.Opcode
+
+object ShortsTextViewFingerprint : MethodFingerprint(
+ returnType = "V",
+ parameters = listOf("L", "L"),
+ opcodes = listOf(
+ Opcode.INVOKE_SUPER, // first instruction of method
+ Opcode.IF_NEZ,
+ Opcode.RETURN_VOID,
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.MOVE_RESULT_OBJECT,
+ Opcode.CHECK_CAST,
+ Opcode.SGET_OBJECT, // insertion point, must be after constructor call to parent class
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.MOVE_RESULT,
+ Opcode.CONST_4,
+ Opcode.IF_EQZ,
+ Opcode.CONST_4,
+ Opcode.IF_EQ,
+ Opcode.CONST_4,
+ Opcode.IF_EQ,
+ Opcode.RETURN_VOID,
+ Opcode.IGET_OBJECT, // TextView field
+ Opcode.CHECK_CAST,
+ Opcode.IGET_BOOLEAN, // boolean field
+ )
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentAtomicReferenceFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentAtomicReferenceFingerprint.kt
index 2385aa904..199f14889 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentAtomicReferenceFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentAtomicReferenceFingerprint.kt
@@ -10,11 +10,10 @@ import org.jf.dexlib2.Opcode
*/
object TextComponentAtomicReferenceFingerprint : MethodFingerprint(
returnType = "L",
- access = AccessFlags.PROTECTED or AccessFlags.FINAL,
+ accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL,
parameters = listOf("L"),
opcodes = listOf(
- Opcode.MOVE_OBJECT, // available unused register
- Opcode.MOVE_OBJECT_FROM16,
+ Opcode.MOVE_OBJECT_FROM16, // available unused register
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16,
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentConstructorFingerprint.kt
index ca29b8eee..5f5c18844 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentConstructorFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentConstructorFingerprint.kt
@@ -6,6 +6,6 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
object TextComponentConstructorFingerprint : MethodFingerprint(
- access = AccessFlags.CONSTRUCTOR or AccessFlags.PRIVATE,
+ accessFlags = AccessFlags.CONSTRUCTOR or AccessFlags.PRIVATE,
strings = listOf("TextComponent")
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentContextFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentContextFingerprint.kt
index 1a23e7046..eee7ab2a2 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentContextFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentContextFingerprint.kt
@@ -10,7 +10,7 @@ import org.jf.dexlib2.Opcode
*/
object TextComponentContextFingerprint : MethodFingerprint(
returnType = "L",
- access = AccessFlags.PROTECTED or AccessFlags.FINAL,
+ accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL,
parameters = listOf("L"),
opcodes = listOf(
Opcode.IGET_OBJECT, // conversion context field name
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt
index 1686c7996..b75fddfcf 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt
@@ -5,7 +5,6 @@ import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.data.toMethodWalker
import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.addInstructions
@@ -19,14 +18,12 @@ import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.*
import app.revanced.patches.youtube.layout.returnyoutubedislike.resource.patch.ReturnYouTubeDislikeResourcePatch
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch
-import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch
-import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
+import app.revanced.patches.youtube.video.videoid.patch.VideoIdPatch
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
@@ -48,7 +45,7 @@ import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
class ReturnYouTubeDislikePatch : BytecodePatch(
listOf(
TextComponentConstructorFingerprint,
- ShortsTextComponentParentFingerprint,
+ ShortsTextViewFingerprint,
DislikesOldLayoutTextViewFingerprint,
LikeFingerprint,
DislikeFingerprint,
@@ -102,18 +99,21 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
val atomicReferenceStartIndex = TextComponentAtomicReferenceFingerprint.result!!
.scanResult.patternScanResult!!.startIndex
+ val insertIndex = atomicReferenceStartIndex + 7
+
textComponentContextFingerprintResult.mutableMethod.apply {
// Get the conversion context obfuscated field name, and the registers for the AtomicReference and CharSequence
val conversionContextFieldReference =
- (instruction(conversionContextIndex) as ReferenceInstruction).reference
+ instruction(conversionContextIndex).reference
+
// any free register
val contextRegister =
- (instruction(atomicReferenceStartIndex) as TwoRegisterInstruction).registerB
- val atomicReferenceRegister =
- (instruction(atomicReferenceStartIndex + 5) as FiveRegisterInstruction).registerC
+ instruction(atomicReferenceStartIndex).registerB
- val insertIndex = atomicReferenceStartIndex + 8
- val moveCharSequenceInstruction = instruction(insertIndex) as TwoRegisterInstruction
+ val atomicReferenceRegister =
+ instruction(atomicReferenceStartIndex + 4).registerC
+
+ val moveCharSequenceInstruction = instruction(insertIndex)
val charSequenceRegister = moveCharSequenceInstruction.registerB
// Insert as first instructions at the control flow label.
@@ -134,35 +134,40 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
// region Hook for Short videos.
- ShortsTextComponentParentFingerprint.result?.let {
- context
- .toMethodWalker(it.method)
- .nextMethod(it.scanResult.patternScanResult!!.endIndex, true)
- .getMethod().let { method ->
- with(method as MutableMethod) {
- // After walking, verify the found method is what's expected.
- if (returnType != ("Ljava/lang/CharSequence;") || parameterTypes.size != 1)
- return PatchResultError("Method signature did not match: $this $parameterTypes")
+ ShortsTextViewFingerprint.result?.let {
+ it.mutableMethod.apply {
+ val patternResult = it.scanResult.patternScanResult!!
- val insertIndex = implementation!!.instructions.size - 1
- val spannedParameterRegister = (instruction(insertIndex) as OneRegisterInstruction).registerA
- val parameter = (instruction(insertIndex - 2) as BuilderInstruction35c).reference
+ // If the field is true, the TextView is for a dislike button.
+ val isDisLikesBooleanReference = instruction(patternResult.endIndex).reference
- if (!parameter.toString().endsWith("Landroid/text/Spanned;"))
- return PatchResultError("Method signature parameter did not match: $parameter")
+ val textViewFieldReference = // Like/Dislike button TextView field
+ instruction(patternResult.endIndex - 2).reference
- insertShorts(insertIndex, spannedParameterRegister)
- }
- }
-
- // Additional hook, called after user dislikes.
- with(it.mutableMethod) {
- val insertIndex = it.scanResult.patternScanResult!!.startIndex + 2
- val overwriteRegister = (implementation!!.instructions.elementAt(insertIndex - 1)
- as OneRegisterInstruction).registerA
- insertShorts(insertIndex, overwriteRegister)
+ // Check if the hooked TextView object is that of the dislike button.
+ // If RYD is disabled, or the TextView object is not that of the dislike button, the execution flow is not interrupted.
+ // Otherwise, the TextView object is modified, and the execution flow is interrupted to prevent it from being changed afterward.
+ val insertIndex = patternResult.startIndex + 6
+ addInstructions(
+ insertIndex, """
+ # Check, if the TextView is for a dislike button
+ iget-boolean v0, p0, $isDisLikesBooleanReference
+ if-eqz v0, :is_like
+
+ # Hook the TextView, if it is for the dislike button
+ iget-object v0, p0, $textViewFieldReference
+ invoke-static {v0}, $INTEGRATIONS_CLASS_DESCRIPTOR->setShortsDislikes(Landroid/view/View;)Z
+ move-result v0
+ if-eqz v0, :ryd_disabled
+ return-void
+
+ :is_like
+ :ryd_disabled
+ nop
+ """
+ )
}
- } ?: return ShortsTextComponentParentFingerprint.toErrorResult()
+ } ?: return ShortsTextViewFingerprint.toErrorResult()
// endregion
@@ -171,9 +176,12 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
DislikesOldLayoutTextViewFingerprint.result?.let {
it.mutableMethod.apply {
val startIndex = it.scanResult.patternScanResult!!.startIndex
- val resourceIdentifierRegister = (instruction(startIndex) as OneRegisterInstruction).registerA
- val textViewRegister = (instruction(startIndex + 4) as OneRegisterInstruction).registerA
- addInstruction(startIndex + 4,
+
+ val resourceIdentifierRegister = instruction(startIndex).registerA
+ val textViewRegister = instruction(startIndex + 4).registerA
+
+ addInstruction(
+ startIndex + 4,
"invoke-static {v$resourceIdentifierRegister, v$textViewRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->setOldUILayoutDislikes(ILandroid/widget/TextView;)V"
)
}
@@ -195,14 +203,5 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
DISLIKE(-1),
REMOVE_LIKE(0)
}
-
- private fun MutableMethod.insertShorts(index: Int, register: Int) {
- addInstructions(
- index, """
- invoke-static {v$register}, $INTEGRATIONS_CLASS_DESCRIPTOR->onShortsComponentCreated(Landroid/text/Spanned;)Landroid/text/Spanned;
- move-result-object v$register
- """
- )
- }
}
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/resource/patch/ReturnYouTubeDislikeResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/resource/patch/ReturnYouTubeDislikeResourcePatch.kt
index 41e8eb34a..866890cbc 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/resource/patch/ReturnYouTubeDislikeResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/resource/patch/ReturnYouTubeDislikeResourcePatch.kt
@@ -26,16 +26,11 @@ class ReturnYouTubeDislikeResourcePatch : ResourcePatch {
}
override fun execute(context: ResourceContext): PatchResult {
- val youtubePackage = "com.google.android.youtube"
SettingsPatch.addPreference(
Preference(
StringResource("revanced_ryd_settings_title", "Return YouTube Dislike"),
- Preference.Intent(
- youtubePackage,
- "ryd_settings",
- "com.google.android.libraries.social.licenses.LicenseActivity"
- ),
StringResource("revanced_ryd_settings_summary", "Settings for Return YouTube Dislike"),
+ SettingsPatch.createReVancedSettingsIntent("ryd_settings")
)
)
// merge strings
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/annotations/WideSearchbarCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/annotations/WideSearchbarCompatibility.kt
index 33672c81c..75d3373ec 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/annotations/WideSearchbarCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/annotations/WideSearchbarCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.searchbar.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class WideSearchbarCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/fingerprints/SetWordmarkHeaderFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/fingerprints/SetWordmarkHeaderFingerprint.kt
index 97cb02215..f0a823398 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/fingerprints/SetWordmarkHeaderFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/fingerprints/SetWordmarkHeaderFingerprint.kt
@@ -18,5 +18,5 @@ object SetWordmarkHeaderFingerprint : MethodFingerprint(
Opcode.CONST,
Opcode.INVOKE_STATIC,
),
- customFingerprint = { methodDef -> methodDef.parameterTypes.first() == "Landroid/widget/ImageView;" }
+ customFingerprint = { methodDef, _ -> methodDef.parameterTypes.first() == "Landroid/widget/ImageView;" }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/patch/WideSearchbarPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/patch/WideSearchbarPatch.kt
index 62bd87fe9..2894e8d63 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/patch/WideSearchbarPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/patch/WideSearchbarPatch.kt
@@ -38,7 +38,6 @@ class WideSearchbarPatch : BytecodePatch(
SwitchPreference(
"revanced_wide_searchbar",
StringResource("revanced_wide_searchbar_enabled_title", "Enable wide search bar"),
- false,
StringResource("revanced_wide_searchbar_summary_on", "Wide search bar is enabled"),
StringResource("revanced_wide_searchbar_summary_off", "Wide search bar is disabled")
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/annotations/SeekbarColorCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/annotations/SeekbarColorCompatibility.kt
new file mode 100644
index 000000000..845bbff94
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/annotations/SeekbarColorCompatibility.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.youtube.layout.seekbar.annotations
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("com.google.android.youtube")])
+@Target(AnnotationTarget.CLASS)
+internal annotation class SeekbarColorCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/fingerprints/CreateDarkThemeSeekbarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/fingerprints/CreateDarkThemeSeekbarFingerprint.kt
new file mode 100644
index 000000000..89aec9b6f
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/fingerprints/CreateDarkThemeSeekbarFingerprint.kt
@@ -0,0 +1,15 @@
+package app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarColorResourcePatch
+import app.revanced.util.patch.indexOfFirstConstantInstruction
+import org.jf.dexlib2.AccessFlags
+
+object CreateDarkThemeSeekbarFingerprint : MethodFingerprint(
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
+ customFingerprint = { method, _ ->
+ method.indexOfFirstConstantInstruction(SeekbarColorResourcePatch.inlineTimeBarColorizedBarPlayedColorDarkId) != -1
+ && method.indexOfFirstConstantInstruction(SeekbarColorResourcePatch.inlineTimeBarPlayedNotHighlightedColorId) != -1
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/fingerprints/SetSeekbarClickedColorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/fingerprints/SetSeekbarClickedColorFingerprint.kt
similarity index 77%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/fingerprints/SetSeekbarClickedColorFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/fingerprints/SetSeekbarClickedColorFingerprint.kt
index 0237c1ec3..abae290d7 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/fingerprints/SetSeekbarClickedColorFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/fingerprints/SetSeekbarClickedColorFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.layout.theme.bytecode.fingerprints
+package app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/patch/SeekbarColorBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/patch/SeekbarColorBytecodePatch.kt
new file mode 100644
index 000000000..752f23afa
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/bytecode/patch/SeekbarColorBytecodePatch.kt
@@ -0,0 +1,85 @@
+package app.revanced.patches.youtube.layout.seekbar.bytecode.patch
+
+import app.revanced.extensions.toErrorResult
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.data.toMethodWalker
+import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.extensions.instruction
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
+import app.revanced.patches.youtube.layout.seekbar.annotations.SeekbarColorCompatibility
+import app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints.CreateDarkThemeSeekbarFingerprint
+import app.revanced.patches.youtube.layout.seekbar.bytecode.fingerprints.SetSeekbarClickedColorFingerprint
+import app.revanced.patches.youtube.layout.theme.bytecode.patch.LithoColorHookPatch
+import app.revanced.patches.youtube.layout.theme.bytecode.patch.LithoColorHookPatch.Companion.lithoColorOverrideHook
+import app.revanced.patches.youtube.layout.seekbar.resource.SeekbarColorResourcePatch
+import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
+import app.revanced.util.patch.indexOfFirstConstantInstruction
+import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
+import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
+
+@Description("Hide or set a custom seekbar color")
+@DependsOn([IntegrationsPatch::class, LithoColorHookPatch::class, SeekbarColorResourcePatch::class])
+@SeekbarColorCompatibility
+@Version("0.0.1")
+class SeekbarColorBytecodePatch : BytecodePatch(
+ listOf(CreateDarkThemeSeekbarFingerprint, SetSeekbarClickedColorFingerprint)
+) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ CreateDarkThemeSeekbarFingerprint.result?.mutableMethod?.apply {
+ var registerIndex = indexOfFirstConstantInstruction(SeekbarColorResourcePatch.inlineTimeBarColorizedBarPlayedColorDarkId) + 2
+ var colorRegister = (instruction(registerIndex) as OneRegisterInstruction).registerA
+ addInstructions(
+ registerIndex + 1,
+ """
+ invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarColorValue(I)I
+ move-result v$colorRegister
+ """
+ )
+
+ registerIndex = indexOfFirstConstantInstruction(SeekbarColorResourcePatch.inlineTimeBarPlayedNotHighlightedColorId) + 2
+ colorRegister = (instruction(registerIndex) as OneRegisterInstruction).registerA
+ addInstructions(
+ registerIndex + 1,
+ """
+ invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarColorValue(I)I
+ move-result v$colorRegister
+ """
+ )
+ } ?: return CreateDarkThemeSeekbarFingerprint.toErrorResult()
+
+ SetSeekbarClickedColorFingerprint.result?.let { result ->
+ result.mutableMethod.let {
+ val setColorMethodIndex = result.scanResult.patternScanResult!!.startIndex + 1
+ val method = context
+ .toMethodWalker(it)
+ .nextMethod(setColorMethodIndex, true)
+ .getMethod() as MutableMethod
+
+ method.apply {
+ val colorRegister = (method.instruction(0) as TwoRegisterInstruction).registerA
+ addInstructions(
+ 0,
+ """
+ invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarColorOverride(I)I
+ move-result v$colorRegister
+ """
+ )
+ }
+ }
+ } ?: return SetSeekbarClickedColorFingerprint.toErrorResult()
+
+ lithoColorOverrideHook(INTEGRATIONS_CLASS_DESCRIPTOR, "getSeekbarColorOverride")
+
+ return PatchResultSuccess()
+ }
+
+ private companion object {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/theme/SeekbarColorPatch;"
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/resource/SeekbarColorResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/resource/SeekbarColorResourcePatch.kt
new file mode 100644
index 000000000..a6bc89a84
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/resource/SeekbarColorResourcePatch.kt
@@ -0,0 +1,45 @@
+package app.revanced.patches.youtube.layout.seekbar.resource
+
+import app.revanced.patcher.data.ResourceContext
+import app.revanced.patcher.patch.*
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import org.w3c.dom.Element
+
+@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
+class SeekbarColorResourcePatch : ResourcePatch {
+ override fun execute(context: ResourceContext): PatchResult {
+ // Edit theme colors via bytecode.
+ // For that the resource id is used in a bytecode patch to change the color.
+
+ val seekbarErrorMessage = "Could not find seekbar resource"
+ inlineTimeBarColorizedBarPlayedColorDarkId = ResourceMappingPatch.resourceMappings
+ .find { it.name == "inline_time_bar_colorized_bar_played_color_dark" }?.id
+ ?: return PatchResultError(seekbarErrorMessage)
+ inlineTimeBarPlayedNotHighlightedColorId = ResourceMappingPatch.resourceMappings
+ .find { it.name == "inline_time_bar_played_not_highlighted_color" }?.id
+ ?: return PatchResultError(seekbarErrorMessage)
+
+ // Edit the resume playback drawable and replace the progress bar with a custom drawable
+ context.xmlEditor["res/drawable/resume_playback_progressbar_drawable.xml"].use { editor ->
+ val layerList = editor.file.getElementsByTagName("layer-list").item(0) as Element
+ val progressNode = layerList.getElementsByTagName("item").item(1) as Element
+ if (!progressNode.getAttributeNode("android:id").value.endsWith("progress")) {
+ return PatchResultError("Could not find progress bar")
+ }
+ val scaleNode = progressNode.getElementsByTagName("scale").item(0) as Element
+ val shapeNode = scaleNode.getElementsByTagName("shape").item(0) as Element
+ val replacementNode = editor.file.createElement(
+ "app.revanced.integrations.patches.theme.ProgressBarDrawable")
+ scaleNode.replaceChild(replacementNode, shapeNode)
+ }
+
+ return PatchResultSuccess()
+ }
+
+ companion object {
+ internal var inlineTimeBarColorizedBarPlayedColorDarkId = -1L
+ internal var inlineTimeBarPlayedNotHighlightedColorId = -1L
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/annotations/SponsorBlockCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/annotations/SponsorBlockCompatibility.kt
index f1d59fb51..f805334ff 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/annotations/SponsorBlockCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/annotations/SponsorBlockCompatibility.kt
@@ -3,8 +3,6 @@ package app.revanced.patches.youtube.layout.sponsorblock.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package("com.google.android.youtube", arrayOf("18.08.37", "18.15.40", "18.16.37"))]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class SponsorBlockCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/ControlsOverlayFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/ControlsOverlayFingerprint.kt
new file mode 100644
index 000000000..a537a12f2
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/ControlsOverlayFingerprint.kt
@@ -0,0 +1,27 @@
+package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import org.jf.dexlib2.AccessFlags
+import org.jf.dexlib2.Opcode
+
+object ControlsOverlayFingerprint : MethodFingerprint(
+ returnType = "V",
+ accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
+ parameters = listOf(),
+ opcodes = listOf(
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.MOVE_RESULT_OBJECT,
+ Opcode.CHECK_CAST, // R.id.inset_overlay_view_layout
+ Opcode.IPUT_OBJECT,
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.CONST,
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.MOVE_RESULT_OBJECT,
+ Opcode.CHECK_CAST,
+ Opcode.NEW_INSTANCE,
+ ),
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass == "Lcom/google/android/apps/youtube/app/player/overlay/YouTubeControlsOverlay;"
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/PlayerOverlaysLayoutInitFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/PlayerOverlaysLayoutInitFingerprint.kt
deleted file mode 100644
index 975bdfe7a..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/PlayerOverlaysLayoutInitFingerprint.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints
-
-
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-
-object PlayerOverlaysLayoutInitFingerprint : MethodFingerprint(
-
- customFingerprint = { methodDef -> methodDef.returnType.endsWith("YouTubePlayerOverlaysLayout;") }
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/RectangleFieldInvalidatorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/RectangleFieldInvalidatorFingerprint.kt
index 822484a89..9aa72efba 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/RectangleFieldInvalidatorFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/RectangleFieldInvalidatorFingerprint.kt
@@ -7,7 +7,7 @@ import org.jf.dexlib2.iface.reference.MethodReference
object RectangleFieldInvalidatorFingerprint : MethodFingerprint(
"V",
- customFingerprint = custom@{ methodDef ->
+ customFingerprint = custom@{ methodDef, _ ->
val instructions = methodDef.implementation?.instructions!!
val instructionCount = instructions.count()
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt
index 931fbfd56..84112ff82 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt
@@ -8,6 +8,7 @@ import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.data.toMethodWalker
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
@@ -22,7 +23,7 @@ import app.revanced.patches.shared.fingerprints.SeekbarOnDrawFingerprint
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
import app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints.AppendTimeFingerprint
-import app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints.PlayerOverlaysLayoutInitFingerprint
+import app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints.ControlsOverlayFingerprint
import app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints.RectangleFieldInvalidatorFingerprint
import app.revanced.patches.youtube.layout.sponsorblock.resource.patch.SponsorBlockResourcePatch
import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatFingerprint
@@ -30,8 +31,8 @@ import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatParen
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.playercontrols.bytecode.patch.PlayerControlsBytecodePatch
import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch
-import app.revanced.patches.youtube.misc.video.information.patch.VideoInformationPatch
-import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch
+import app.revanced.patches.youtube.video.information.patch.VideoInformationPatch
+import app.revanced.patches.youtube.video.videoid.patch.VideoIdPatch
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.*
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
@@ -60,7 +61,7 @@ class SponsorBlockBytecodePatch : BytecodePatch(
listOf(
SeekbarFingerprint,
AppendTimeFingerprint,
- PlayerOverlaysLayoutInitFingerprint,
+ ControlsOverlayFingerprint,
AutoRepeatParentFingerprint,
)
) {
@@ -102,17 +103,18 @@ class SponsorBlockBytecodePatch : BytecodePatch(
val seekbarMethodInstructions = seekbarMethod.implementation!!.instructions
/*
- * Get the instance of the seekbar rectangle
+ * Get left and right of seekbar rectangle
*/
- for ((index, instruction) in seekbarMethodInstructions.withIndex()) {
- if (instruction.opcode != Opcode.MOVE_OBJECT_FROM16) continue
- seekbarMethod.addInstruction(
- index + 1,
- "invoke-static/range {p0 .. p0}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;)V"
- )
- break
+ val moveRectangleToRegisterIndex = seekbarMethodInstructions.indexOfFirst {
+ it.opcode == Opcode.MOVE_OBJECT_FROM16
}
+ seekbarMethod.addInstruction(
+ moveRectangleToRegisterIndex + 1,
+ "invoke-static/range {p0 .. p0}, " +
+ "$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;)V"
+ )
+
for ((index, instruction) in seekbarMethodInstructions.withIndex()) {
if (instruction.opcode != Opcode.INVOKE_STATIC) continue
@@ -124,38 +126,15 @@ class SponsorBlockBytecodePatch : BytecodePatch(
// set the thickness of the segment
seekbarMethod.addInstruction(
insertIndex,
- "invoke-static {v${invokeInstruction.registerC}}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarThickness(I)V"
+ "invoke-static {v${invokeInstruction.registerC}}, " +
+ "$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarThickness(I)V"
)
break
}
- /*
- * Set rectangle absolute left and right positions
- */
- val drawRectangleInstructions = seekbarMethodInstructions.withIndex().filter { (_, instruction) ->
- instruction is ReferenceInstruction && (instruction.reference as? MethodReference)?.name == "drawRect"
- }.map { (index, instruction) -> // TODO: improve code
- index to (instruction as FiveRegisterInstruction).registerD
- }
-
- val (indexRight, rectangleRightRegister) = drawRectangleInstructions[0]
- val (indexLeft, rectangleLeftRegister) = drawRectangleInstructions[3]
-
- // order of operation is important here due to the code above which has to be improved
- // the reason for that is that we get the index, add instructions and then the offset would be wrong
- seekbarMethod.addInstruction(
- indexLeft + 1,
- "invoke-static {v$rectangleLeftRegister}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarAbsoluteLeft(Landroid/graphics/Rect;)V"
- )
- seekbarMethod.addInstruction(
- indexRight + 1,
- "invoke-static {v$rectangleRightRegister}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarAbsoluteRight(Landroid/graphics/Rect;)V"
- )
-
/*
* Draw segment
*/
-
// Find the drawCircle call and draw the segment before it
for (i in seekbarMethodInstructions.size - 1 downTo 0) {
val invokeInstruction = seekbarMethodInstructions[i] as? ReferenceInstruction ?: continue
@@ -198,8 +177,8 @@ class SponsorBlockBytecodePatch : BytecodePatch(
method.addInstructions(
moveResultInstructionIndex + 1, // insert right after moving the view to the register and use that register
"""
- invoke-static {v$inflatedViewRegister}, $INTEGRATIONS_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->initialize(Ljava/lang/Object;)V
- invoke-static {v$inflatedViewRegister}, $INTEGRATIONS_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->initialize(Ljava/lang/Object;)V
+ invoke-static {v$inflatedViewRegister}, $INTEGRATIONS_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->initialize(Landroid/view/View;)V
+ invoke-static {v$inflatedViewRegister}, $INTEGRATIONS_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->initialize(Landroid/view/View;)V
"""
)
}
@@ -240,10 +219,16 @@ class SponsorBlockBytecodePatch : BytecodePatch(
VideoInformationPatch.onCreateHook(INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR, "initialize")
// initialize the sponsorblock view
- PlayerOverlaysLayoutInitFingerprint.result!!.mutableMethod.addInstruction(
- 6, // after inflating the view
- "invoke-static {p0}, $INTEGRATIONS_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR->initialize(Ljava/lang/Object;)V"
- )
+ ControlsOverlayFingerprint.result?.let {
+ val startIndex = it.scanResult.patternScanResult!!.startIndex
+ it.mutableMethod.apply {
+ val frameLayoutRegister = (instruction(startIndex + 2) as OneRegisterInstruction).registerA
+ addInstruction(
+ startIndex + 3,
+ "invoke-static {v$frameLayoutRegister}, $INTEGRATIONS_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR->initialize(Landroid/view/ViewGroup;)V"
+ )
+ }
+ } ?: return ControlsOverlayFingerprint.toErrorResult()
// get rectangle field name
RectangleFieldInvalidatorFingerprint.resolve(context, seekbarSignatureResult.classDef)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/resource/patch/SponsorBlockResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/resource/patch/SponsorBlockResourcePatch.kt
index 7c59a9ace..c5b97a993 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/resource/patch/SponsorBlockResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/resource/patch/SponsorBlockResourcePatch.kt
@@ -10,7 +10,6 @@ import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.Preference
import app.revanced.patches.shared.settings.preference.impl.StringResource
-import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources
@@ -18,22 +17,16 @@ import app.revanced.util.resources.ResourceUtils.copyXmlNode
import app.revanced.util.resources.ResourceUtils.mergeStrings
@Name("sponsorblock-resource-patch")
-@SponsorBlockCompatibility
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
@Version("0.0.1")
class SponsorBlockResourcePatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
- val youtubePackage = "com.google.android.youtube"
SettingsPatch.addPreference(
Preference(
- StringResource("sb_settings", "SponsorBlock"),
- Preference.Intent(
- youtubePackage,
- "sponsorblock_settings",
- "com.google.android.libraries.social.licenses.LicenseActivity"
- ),
+ StringResource("revanced_sponsorblock_settings_title", "SponsorBlock"),
StringResource("revanced_sponsorblock_settings_summary", "SponsorBlock related settings"),
+ SettingsPatch.createReVancedSettingsIntent("sponsorblock_settings")
)
)
val classLoader = this.javaClass.classLoader
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/annotations/SpoofAppVersionCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/annotations/SpoofAppVersionCompatibility.kt
index 82d01af3f..c64f17745 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/annotations/SpoofAppVersionCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/annotations/SpoofAppVersionCompatibility.kt
@@ -3,23 +3,7 @@ package app.revanced.patches.youtube.layout.spoofappversion.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class SpoofAppVersionCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/bytecode/patch/SpoofAppVersionPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/bytecode/patch/SpoofAppVersionPatch.kt
index add8947a6..2567f3fc1 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/bytecode/patch/SpoofAppVersionPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/bytecode/patch/SpoofAppVersionPatch.kt
@@ -37,12 +37,12 @@ class SpoofAppVersionPatch : BytecodePatch(
SwitchPreference(
"revanced_spoof_app_version",
StringResource("revanced_spoof_app_version_title", "Spoof app version"),
- false,
StringResource("revanced_spoof_app_version_summary_on", "Version spoofed"),
StringResource("revanced_spoof_app_version_summary_off", "Version not spoofed"),
StringResource("revanced_spoof_app_version_user_dialog_message",
- "App version will be spoofed to an older version of YouTube. This will change the appearance of the app, but unknown side effects may occur."
- + " If later turned off, the old UI may remain until you log out or clear the app data.")
+ "App version will be spoofed to an older version of YouTube."
+ + "\\n\\nThis will change the appearance and features of the app, but unknown side effects may occur."
+ + "\\n\\nIf later turned off, the old UI may remain until you log out or clear the app data.")
),
ListPreference(
"revanced_spoof_app_version_target",
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/annotations/StartupShortsResetCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/annotations/StartupShortsResetCompatibility.kt
index 88b5a9297..72b516851 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/annotations/StartupShortsResetCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/annotations/StartupShortsResetCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.layout.startupshortsreset.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class StartupShortsResetCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/patch/DisableShortsOnStartupPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/patch/DisableShortsOnStartupPatch.kt
index af2fae09c..8be60b6a9 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/patch/DisableShortsOnStartupPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/patch/DisableShortsOnStartupPatch.kt
@@ -31,11 +31,10 @@ class DisableShortsOnStartupPatch : BytecodePatch(
override fun execute(context: BytecodeContext): PatchResult {
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
SwitchPreference(
- "revanced_startup_shorts_player_enabled",
- StringResource("revanced_startup_shorts_player_title", "Disable shorts player at app startup"),
- false,
- StringResource("revanced_startup_shorts_player_summary_on", "Shorts player is disabled at app startup"),
- StringResource("revanced_startup_shorts_player_summary_off", "Shorts player is enabled at app startup")
+ "revanced_disable_resuming_shorts_player",
+ StringResource("revanced_disable_resuming_shorts_player_title", "Disable shorts player at app startup"),
+ StringResource("revanced_disable_resuming_shorts_player_summary_on", "Shorts player is disabled at app startup"),
+ StringResource("revanced_disable_resuming_shorts_player_summary_off", "Shorts player is enabled at app startup")
)
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/annotations/TabletMiniPlayerCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/annotations/TabletMiniPlayerCompatibility.kt
index 21e909201..ded1563ed 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/annotations/TabletMiniPlayerCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/annotations/TabletMiniPlayerCompatibility.kt
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.layout.tabletminiplayer.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility([Package("com.google.android.youtube", arrayOf("18.15.40", "18.16.37"))])
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class TabletMiniPlayerCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/patch/TabletMiniPlayerPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/patch/TabletMiniPlayerPatch.kt
index 51ef60315..26994af50 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/patch/TabletMiniPlayerPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/patch/TabletMiniPlayerPatch.kt
@@ -42,7 +42,6 @@ class TabletMiniPlayerPatch : BytecodePatch(
SwitchPreference(
"revanced_tablet_miniplayer",
StringResource("revanced_tablet_miniplayer_title", "Enable tablet mini player"),
- false,
StringResource("revanced_tablet_miniplayer_summary_on", "Mini player is enabled"),
StringResource("revanced_tablet_miniplayer_summary_off", "Mini player is disabled")
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/fingerprints/CreateDarkThemeSeekbarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/fingerprints/CreateDarkThemeSeekbarFingerprint.kt
deleted file mode 100644
index 98baa9d69..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/fingerprints/CreateDarkThemeSeekbarFingerprint.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package app.revanced.patches.youtube.layout.theme.bytecode.fingerprints
-
-import app.revanced.patcher.extensions.or
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import app.revanced.patches.youtube.layout.theme.bytecode.fingerprints.CreateDarkThemeSeekbarFingerprint.indexOfInstructionWithSeekbarId
-import app.revanced.patches.youtube.layout.theme.resource.ThemeResourcePatch
-import org.jf.dexlib2.AccessFlags
-import org.jf.dexlib2.Opcode
-import org.jf.dexlib2.iface.Method
-import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
-
-object CreateDarkThemeSeekbarFingerprint : MethodFingerprint(
- access = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
- customFingerprint = { method -> method.indexOfInstructionWithSeekbarId != -1 },
-) {
- /**
- * The index of the instruction that loads the resource id of the seekbar.
- */
- internal val Method.indexOfInstructionWithSeekbarId
- get() = implementation?.let {
- it.instructions.indexOfFirst { instruction ->
- instruction.opcode == Opcode.CONST && (instruction as WideLiteralInstruction).wideLiteral == ThemeResourcePatch.inlineTimeBarColorizedBarPlayedColorDarkId
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/fingerprints/LithoThemeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/fingerprints/LithoThemeFingerprint.kt
similarity index 90%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/theme/fingerprints/LithoThemeFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/fingerprints/LithoThemeFingerprint.kt
index ba6e29cf5..ffb29604f 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/fingerprints/LithoThemeFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/fingerprints/LithoThemeFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.layout.theme.fingerprints
+package app.revanced.patches.youtube.layout.theme.bytecode.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/LithoColorHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/LithoColorHookPatch.kt
new file mode 100644
index 000000000..0568876ef
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/LithoColorHookPatch.kt
@@ -0,0 +1,47 @@
+package app.revanced.patches.youtube.layout.theme.bytecode.patch
+
+import app.revanced.extensions.toErrorResult
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
+import app.revanced.patches.youtube.layout.theme.annotations.ThemeCompatibility
+import app.revanced.patches.youtube.layout.theme.bytecode.fingerprints.LithoThemeFingerprint
+
+@Name("litho-color-hook")
+@Description("Adds a hook to set color of Litho components.")
+@ThemeCompatibility
+@Version("0.0.1")
+class LithoColorHookPatch : BytecodePatch(listOf(LithoThemeFingerprint)) {
+ override fun execute(context: BytecodeContext): PatchResult {
+ LithoThemeFingerprint.result?.let {
+ insertionIndex = it.scanResult.patternScanResult!!.endIndex - 1
+ colorRegister = "p1"
+ insertionMethod = it.mutableMethod
+ } ?: return LithoThemeFingerprint.toErrorResult()
+
+ return PatchResultSuccess()
+ }
+ companion object {
+ private var insertionIndex : Int = -1
+ private lateinit var colorRegister : String
+ private lateinit var insertionMethod : MutableMethod
+
+ internal fun lithoColorOverrideHook(targetMethodClass: String, targetMethodName: String) {
+ insertionMethod.addInstructions(
+ insertionIndex,
+ """
+ invoke-static {$colorRegister}, $targetMethodClass->$targetMethodName(I)I
+ move-result $colorRegister
+ """
+ )
+ insertionIndex += 2
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/ThemeBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/ThemeBytecodePatch.kt
index fbc8dcefa..1889ed7a8 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/ThemeBytecodePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/ThemeBytecodePatch.kt
@@ -1,77 +1,58 @@
package app.revanced.patches.youtube.layout.theme.bytecode.patch
-import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.data.toMethodWalker
-import app.revanced.patcher.extensions.addInstructions
-import app.revanced.patcher.extensions.instruction
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.PatchResult
-import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
+import app.revanced.patches.youtube.layout.seekbar.bytecode.patch.SeekbarColorBytecodePatch
import app.revanced.patches.youtube.layout.theme.annotations.ThemeCompatibility
-import app.revanced.patches.youtube.layout.theme.bytecode.fingerprints.CreateDarkThemeSeekbarFingerprint
-import app.revanced.patches.youtube.layout.theme.bytecode.fingerprints.CreateDarkThemeSeekbarFingerprint.indexOfInstructionWithSeekbarId
-import app.revanced.patches.youtube.layout.theme.bytecode.fingerprints.SetSeekbarClickedColorFingerprint
import app.revanced.patches.youtube.layout.theme.resource.ThemeResourcePatch
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
@Patch
@Name("theme")
@Description("Applies a custom theme.")
-@DependsOn([ThemeLithoComponentsPatch::class, ThemeResourcePatch::class, IntegrationsPatch::class])
+@DependsOn([LithoColorHookPatch::class, SeekbarColorBytecodePatch::class, ThemeResourcePatch::class])
@ThemeCompatibility
@Version("0.0.1")
-class ThemeBytecodePatch : BytecodePatch(
- listOf(CreateDarkThemeSeekbarFingerprint, SetSeekbarClickedColorFingerprint)
-) {
+class ThemeBytecodePatch : BytecodePatch() {
+
override fun execute(context: BytecodeContext): PatchResult {
- CreateDarkThemeSeekbarFingerprint.result?.let {
- val putColorValueIndex = it.method.indexOfInstructionWithSeekbarId!! + 3
+ LithoColorHookPatch.lithoColorOverrideHook(INTEGRATIONS_CLASS_DESCRIPTOR, "getValue")
- it.mutableMethod.apply {
- val overrideRegister = (instruction(putColorValueIndex) as TwoRegisterInstruction).registerA
-
- addInstructions(
- putColorValueIndex,
- """
- invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarColorValue()I
- move-result v$overrideRegister
- """
- )
- }
- } ?: return CreateDarkThemeSeekbarFingerprint.toErrorResult()
-
- SetSeekbarClickedColorFingerprint.result?.let { result ->
- result.mutableMethod.let {
- val setColorMethodIndex = result.scanResult.patternScanResult!!.startIndex + 1
- val method = context
- .toMethodWalker(it)
- .nextMethod(setColorMethodIndex, true)
- .getMethod() as MutableMethod
-
- method.apply {
- val colorRegister = (method.instruction(0) as TwoRegisterInstruction).registerA
- addInstructions(
- 0,
- """
- invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarClickedColorValue(I)I
- move-result v$colorRegister
- """
- )
- }
- }
- } ?: return SetSeekbarClickedColorFingerprint.toErrorResult()
return PatchResultSuccess()
}
- private companion object {
- private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/theme/ThemePatch;"
+ companion object : OptionsContainer() {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/theme/ThemeLithoComponentsPatch;"
+
+ var darkThemeBackgroundColor: String? by option(
+ PatchOption.StringOption(
+ key = "darkThemeBackgroundColor",
+ default = "@android:color/black",
+ title = "Background color for the dark theme",
+ description = "The background color of the dark theme. Can be a hex color or a resource reference.",
+ )
+ )
+
+ var lightThemeBackgroundColor: String? by option(
+ PatchOption.StringOption(
+ key = "lightThemeBackgroundColor",
+ default = "@android:color/white",
+ title = "Background color for the light theme",
+ description = "The background color of the light theme. Can be a hex color or a resource reference.",
+ )
+ )
+
+ var splashScreenBackgroundColor: String? by option(
+ PatchOption.StringOption(
+ key = "splashScreenBackgroundColor",
+ default = "@android:color/black",
+ title = "Background color for the splash screen",
+ description = "The background color of the splash screen. Can be a hex color or a resource reference.",
+ )
+ )
}
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/ThemeLithoComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/ThemeLithoComponentsPatch.kt
deleted file mode 100644
index cfcf75ed0..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/ThemeLithoComponentsPatch.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-package app.revanced.patches.youtube.layout.theme.bytecode.patch
-
-import app.revanced.extensions.toErrorResult
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.annotation.Version
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.addInstructions
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.PatchResult
-import app.revanced.patcher.patch.PatchResultSuccess
-import app.revanced.patches.youtube.layout.theme.annotations.ThemeCompatibility
-import app.revanced.patches.youtube.layout.theme.fingerprints.LithoThemeFingerprint
-
-@Name("theme-litho-components")
-@Description("Applies a custom theme to Litho components.")
-@ThemeCompatibility
-@Version("0.0.1")
-class ThemeLithoComponentsPatch : BytecodePatch(listOf(LithoThemeFingerprint)) {
- override fun execute(context: BytecodeContext): PatchResult {
- LithoThemeFingerprint.result?.let {
- it.mutableMethod.apply {
- val patchIndex = it.scanResult.patternScanResult!!.endIndex - 1
-
- addInstructions(
- patchIndex,
- """
- invoke-static {p1}, $INTEGRATIONS_CLASS_DESCRIPTOR->getValue(I)I
- move-result p1
- """
- )
- }
- } ?: return LithoThemeFingerprint.toErrorResult()
- return PatchResultSuccess()
- }
-
- private companion object {
- private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/theme/ThemeLithoComponentsPatch;"
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/resource/ThemeResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/resource/ThemeResourcePatch.kt
index 12d396093..a69278309 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/resource/ThemeResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/resource/ThemeResourcePatch.kt
@@ -1,15 +1,18 @@
package app.revanced.patches.youtube.layout.theme.resource
import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.*
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.InputType
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.TextPreference
+import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.darkThemeBackgroundColor
+import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.lightThemeBackgroundColor
+import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.splashScreenBackgroundColor
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-import app.revanced.util.resources.ResourceUtils
-import app.revanced.util.resources.ResourceUtils.copyResources
import org.w3c.dom.Element
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
@@ -19,73 +22,88 @@ class ThemeResourcePatch : ResourcePatch {
TextPreference(
"revanced_seekbar_color",
StringResource("revanced_seekbar_color_title", "Seekbar color"),
- InputType.STRING,
- "#ffff0000",
StringResource(
"revanced_seekbar_color_summary",
- "The color of the seekbar for the dark theme."
- )
+ "The color of the seekbar"
+ ),
+ InputType.TEXT_CAP_CHARACTERS
),
)
- // Edit theme colors via bytecode.
- // For that the resource id is used in a bytecode patch to change the color.
-
- inlineTimeBarColorizedBarPlayedColorDarkId = ResourceMappingPatch.resourceMappings
- .find { it.name == "inline_time_bar_colorized_bar_played_color_dark" }?.id
- ?: return PatchResultError("Could not find seekbar resource")
-
-
- val darkThemeBackgroundColor = darkThemeBackgroundColor!!
- val lightThemeBackgroundColor = lightThemeBackgroundColor!!
-
// Edit theme colors via resources.
context.xmlEditor["res/values/colors.xml"].use { editor ->
val resourcesNode = editor.file.getElementsByTagName("resources").item(0) as Element
- for (i in 0 until resourcesNode.childNodes.length) {
- val node = resourcesNode.childNodes.item(i) as? Element ?: continue
+ val children = resourcesNode.childNodes
+ for (i in 0 until children.length) {
+ val node = children.item(i) as? Element ?: continue
node.textContent = when (node.getAttribute("name")) {
"yt_black0", "yt_black1", "yt_black1_opacity95", "yt_black1_opacity98", "yt_black2", "yt_black3",
"yt_black4", "yt_status_bar_background_dark", "material_grey_850" -> darkThemeBackgroundColor
+ ?: continue
"yt_white1", "yt_white1_opacity95", "yt_white1_opacity98",
"yt_white2", "yt_white3", "yt_white4",
- -> lightThemeBackgroundColor
+ -> lightThemeBackgroundColor ?: continue
else -> continue
}
}
}
- // Copy the resource file to change the splash screen color.
- context.copyResources(
- "theme", ResourceUtils.ResourceGroup("values-night-v31", "styles.xml")
- )
+ splashScreenBackgroundColor ?: return PatchResultSuccess()
+
+ // Edit splash screen background color for Android 11 and below.
+ context.xmlEditor["res/values/styles.xml"].use {
+ val resourcesNode = it.file.getElementsByTagName("resources").item(0) as Element
+
+ val children = resourcesNode.childNodes
+ for (i in 0 until children.length) {
+ val node = children.item(i) as? Element ?: continue
+
+ if (node.tagName != "style") continue
+
+ val name = node.getAttribute("name")
+ if (name != LAUNCHER_STYLE_NAME) continue
+
+ it.file.createElement("item").apply {
+ setAttribute("name", "android:windowSplashScreenBackground")
+ textContent = splashScreenBackgroundColor
+ }.also(node::appendChild)
+
+ break
+ }
+ }
+
+ // Edit splash screen background color for Android 12+.
+
+ // Add the splash screen background color to the colors.xml file.
+ context.xmlEditor["res/values/colors.xml"].use {
+ val resourcesNode = it.file.getElementsByTagName("resources").item(0) as Element
+
+ it.file.createElement("color").apply {
+ setAttribute("name", COLOR_NAME)
+ setAttribute("category", "color")
+ textContent = splashScreenBackgroundColor
+ }.also(resourcesNode::appendChild)
+ }
+
+ // Point to the splash screen background color.
+ context.xmlEditor["res/drawable/quantum_launchscreen_youtube.xml"].use {
+ val node = it.file.getElementsByTagName("layer-list").item(0) as Element
+
+ val backgroundColorItem = node.childNodes.item(1) as Element
+ backgroundColorItem.apply {
+ setAttribute("android:drawable", "@color/$COLOR_NAME")
+ }
+ }
return PatchResultSuccess()
}
- companion object : OptionsContainer() {
- internal var inlineTimeBarColorizedBarPlayedColorDarkId = -1L
-
- var darkThemeBackgroundColor: String? by option(
- PatchOption.StringOption(
- key = "darkThemeBackgroundColor",
- default = "@android:color/black",
- title = "Background color for the dark theme",
- description = "The background color of the dark theme. Can be a hex color or a resource reference.",
- )
- )
-
- var lightThemeBackgroundColor: String? by option(
- PatchOption.StringOption(
- key = "lightThemeBackgroundColor",
- default = "@android:color/white",
- title = "Background color for the light theme",
- description = "The background color of the light theme. Can be a hex color or a resource reference.",
- )
- )
+ private companion object {
+ private const val LAUNCHER_STYLE_NAME = "Base.Theme.YouTube.Launcher"
+ private const val COLOR_NAME = "splash_background_color"
}
-}
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/annotations/AutoRepeatCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/annotations/AutoRepeatCompatibility.kt
index ad3f149b7..ab04bfe8d 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/annotations/AutoRepeatCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/annotations/AutoRepeatCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.misc.autorepeat.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class AutoRepeatCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/fingerprints/AutoRepeatFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/fingerprints/AutoRepeatFingerprint.kt
index a16683b14..c784ba8a0 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/fingerprints/AutoRepeatFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/fingerprints/AutoRepeatFingerprint.kt
@@ -8,5 +8,7 @@ object AutoRepeatFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf(),
- customFingerprint = { methodDef -> methodDef.implementation!!.instructions.count() == 3 && methodDef.annotations.isEmpty()}
+ customFingerprint = { methodDef, _ ->
+ methodDef.implementation!!.instructions.count() == 3 && methodDef.annotations.isEmpty()
+ }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/patch/AutoRepeatPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/patch/AutoRepeatPatch.kt
index 38617967d..08b2798da 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/patch/AutoRepeatPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/patch/AutoRepeatPatch.kt
@@ -35,9 +35,8 @@ class AutoRepeatPatch : BytecodePatch(
override fun execute(context: BytecodeContext): PatchResult {
SettingsPatch.PreferenceScreen.MISC.addPreferences(
SwitchPreference(
- "revanced_pref_auto_repeat",
- StringResource("revanced_auto_repeat_enabled_title", "Enable auto-repeat"),
- false,
+ "revanced_auto_repeat",
+ StringResource("revanced_auto_repeat_title", "Enable auto-repeat"),
StringResource("revanced_auto_repeat_summary_on", "Auto-repeat is enabled"),
StringResource("revanced_auto_repeat_summary_off", "Auto-repeat is disabled")
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/patch/DebuggingPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/patch/DebuggingPatch.kt
index ef0dba238..d5f279458 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/patch/DebuggingPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/patch/DebuggingPatch.kt
@@ -26,43 +26,39 @@ class DebuggingPatch : ResourcePatch {
override fun execute(context: ResourceContext): PatchResult {
SettingsPatch.PreferenceScreen.MISC.addPreferences(
app.revanced.patches.shared.settings.preference.impl.PreferenceScreen(
- "revanced_debug",
- StringResource("revanced_debug_title", "Debugging"),
+ "revanced_debug_preference_screen",
+ StringResource("revanced_debug_preference_screen_title", "Debugging"),
listOf(
SwitchPreference(
- "revanced_debug_enabled",
- StringResource("revanced_debug_enabled_title", "Debug logging"),
- false,
+ "revanced_debug",
+ StringResource("revanced_debug_title", "Debug logging"),
StringResource("revanced_debug_summary_on", "Debug logs are enabled"),
StringResource("revanced_debug_summary_off", "Debug logs are disabled")
),
SwitchPreference(
- "revanced_debug_stacktrace_enabled",
+ "revanced_debug_stacktrace",
StringResource(
- "revanced_debug_stacktrace_enabled_title",
+ "revanced_debug_stacktrace_title",
"Log stack traces"
),
- false,
StringResource("revanced_debug_stacktrace_summary_on", "Debug logs include stack trace"),
StringResource("revanced_debug_stacktrace_summary_off", "Debug logs do not include stack trace")
),
SwitchPreference(
- "revanced_debug_toast_on_error_enabled",
+ "revanced_debug_toast_on_error",
StringResource(
- "revanced_debug_toast_on_error_enabled_title",
+ "revanced_debug_toast_on_error_title",
"Show toast on ReVanced error"
),
- true,
StringResource("revanced_debug_toast_on_error_summary_on", "Toast shown if error occurs"),
StringResource("revanced_debug_toast_on_error_summary_off", "Toast not shown if error occurs"),
StringResource("revanced_debug_toast_on_error_user_dialog_message",
- "Turning off error toasts hides all ReVanced error notifications." +
- " This includes hiding normal network connection timeouts, " +
- "but also hides notification of any unexpected and more serious errors."
+ "Turning off error toasts hides all ReVanced error notifications."
+ + "\\n\\nYou will not be notified of any unexpected events."
)
),
),
- StringResource("revanced_debug_summary", "Enable or disable debugging options")
+ StringResource("revanced_debug_preference_screen_summary", "Enable or disable debugging options")
)
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/annotation/FixBackToExitGestureCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/annotation/FixBackToExitGestureCompatibility.kt
index f04329dab..8a470352b 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/annotation/FixBackToExitGestureCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/annotation/FixBackToExitGestureCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.misc.fix.backtoexitgesture.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class FixBackToExitGestureCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/OnBackPressedFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/OnBackPressedFingerprint.kt
index 010fd65ca..06f039393 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/OnBackPressedFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/OnBackPressedFingerprint.kt
@@ -7,7 +7,7 @@ object OnBackPressedFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.RETURN_VOID
),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("WatchWhileActivity;")
&& methodDef.name == "onBackPressed"
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/RecyclerViewTopScrollingParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/RecyclerViewTopScrollingParentFingerprint.kt
index 09964ba5f..0d4425b90 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/RecyclerViewTopScrollingParentFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/fingerprints/RecyclerViewTopScrollingParentFingerprint.kt
@@ -14,7 +14,7 @@ object RecyclerViewTopScrollingParentFingerprint : MethodFingerprint(
Opcode.INVOKE_VIRTUAL,
Opcode.NEW_INSTANCE
),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.name == ""
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/annotations/ClientSpoofCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/annotations/ClientSpoofCompatibility.kt
new file mode 100644
index 000000000..13e9c51b5
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/annotations/ClientSpoofCompatibility.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.youtube.misc.fix.playback.annotations
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
+@Target(AnnotationTarget.CLASS)
+internal annotation class ClientSpoofCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/SubtitleWindowSettingsConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/SubtitleWindowSettingsConstructorFingerprint.kt
index 0cb104f24..f37201f86 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/SubtitleWindowSettingsConstructorFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/SubtitleWindowSettingsConstructorFingerprint.kt
@@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object SubtitleWindowSettingsConstructorFingerprint : MethodFingerprint(
parameters = listOf("I", "I", "I", "Z", "Z"),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lcom/google/android/libraries/youtube/player/subtitles/model/SubtitleWindowSettings;"
&& methodDef.name == ""
}
diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/fix/spoof/fingerprints/UserAgentHeaderBuilderFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/UserAgentHeaderBuilderFingerprint.kt
similarity index 82%
rename from src/main/kotlin/app/revanced/patches/shared/misc/fix/spoof/fingerprints/UserAgentHeaderBuilderFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/UserAgentHeaderBuilderFingerprint.kt
index f3cf363e3..5428c2a4d 100644
--- a/src/main/kotlin/app/revanced/patches/shared/misc/fix/spoof/fingerprints/UserAgentHeaderBuilderFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/UserAgentHeaderBuilderFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.shared.misc.fix.spoof.fingerprints
+package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/fix/spoof/patch/ClientSpoofPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/ClientSpoofPatch.kt
similarity index 77%
rename from src/main/kotlin/app/revanced/patches/shared/misc/fix/spoof/patch/ClientSpoofPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/ClientSpoofPatch.kt
index 161f960ee..b06a4bfa0 100644
--- a/src/main/kotlin/app/revanced/patches/shared/misc/fix/spoof/patch/ClientSpoofPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/ClientSpoofPatch.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.shared.misc.fix.spoof.patch
+package app.revanced.patches.youtube.misc.fix.playback.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
@@ -12,9 +12,8 @@ import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.shared.misc.fix.spoof.annotations.ClientSpoofCompatibility
-import app.revanced.patches.shared.misc.fix.spoof.fingerprints.UserAgentHeaderBuilderFingerprint
-import app.revanced.patches.youtube.misc.fix.playback.patch.SpoofSignatureVerificationPatch
+import app.revanced.patches.youtube.misc.fix.playback.annotations.ClientSpoofCompatibility
+import app.revanced.patches.youtube.misc.fix.playback.fingerprints.UserAgentHeaderBuilderFingerprint
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
@Patch
@@ -30,7 +29,8 @@ class ClientSpoofPatch : BytecodePatch(
UserAgentHeaderBuilderFingerprint.result?.let { result ->
val insertIndex = result.scanResult.patternScanResult!!.endIndex
result.mutableMethod.apply {
- val packageNameRegister = (instruction(insertIndex) as FiveRegisterInstruction).registerD
+ val packageNameRegister = instruction(insertIndex).registerD
+
addInstruction(insertIndex, "const-string v$packageNameRegister, \"$ORIGINAL_PACKAGE_NAME\"")
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/SpoofSignatureVerificationPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/SpoofSignatureVerificationPatch.kt
index 1f6d84c6d..db5229f94 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/SpoofSignatureVerificationPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/SpoofSignatureVerificationPatch.kt
@@ -21,7 +21,7 @@ import app.revanced.patches.youtube.misc.fix.playback.fingerprints.SubtitleWindo
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch
+import app.revanced.patches.youtube.video.videoid.patch.VideoIdPatch
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@Name("spoof-signature-verification")
@@ -45,12 +45,11 @@ class SpoofSignatureVerificationPatch : BytecodePatch(
SwitchPreference(
"revanced_spoof_signature_verification",
StringResource("revanced_spoof_signature_verification_title", "Spoof app signature"),
- true,
StringResource("revanced_spoof_signature_verification_summary_on",
"App signature spoofed\\n\\n"
+ "Side effects include:\\n"
+ "• End screen cards are always hidden\\n"
- + "• Download button may be hidden"),
+ + "• Downloading videos may not work"),
StringResource("revanced_spoof_signature_verification_summary_off", "App signature not spoofed"),
StringResource("revanced_spoof_signature_verification_user_dialog_message",
"Turning off this setting may cause playback issues.")
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/annotations/HDRBrightnessCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/annotations/HDRBrightnessCompatibility.kt
deleted file mode 100644
index 44be49f99..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/annotations/HDRBrightnessCompatibility.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package app.revanced.patches.youtube.misc.hdrbrightness.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class HDRBrightnessCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/annotations/IntegrationsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/annotations/IntegrationsCompatibility.kt
index 787203464..0bdca1b8a 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/annotations/IntegrationsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/annotations/IntegrationsCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.misc.integrations.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class IntegrationsCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/EmbeddedPlayerControlsOverlayFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/EmbeddedPlayerControlsOverlayFingerprint.kt
new file mode 100644
index 000000000..395fd022b
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/EmbeddedPlayerControlsOverlayFingerprint.kt
@@ -0,0 +1,15 @@
+package app.revanced.patches.youtube.misc.integrations.fingerprints
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
+import org.jf.dexlib2.AccessFlags
+
+object EmbeddedPlayerControlsOverlayFingerprint : IntegrationsFingerprint(
+ accessFlags = AccessFlags.PRIVATE or AccessFlags.CONSTRUCTOR,
+ returnType = "V",
+ parameters = listOf("L", "L", "L"),
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass.startsWith("Lcom/google/android/apps/youtube/embeddedplayer/service/ui/overlays/controlsoverlay/remoteloaded/")
+ },
+ contextRegisterResolver = { it.implementation!!.registerCount - it.parameters.size }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ServiceFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ServiceFingerprint.kt
index 813aaf573..dd5868d78 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ServiceFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ServiceFingerprint.kt
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.misc.integrations.fingerprints
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
object ServiceFingerprint : IntegrationsFingerprint(
- customFingerprint = { methodDef -> methodDef.definingClass.endsWith("ApiPlayerService;") && methodDef.name == "" },
+ customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("ApiPlayerService;") && methodDef.name == "" },
contextRegisterResolver = { it.implementation!!.registerCount - it.parameters.size }
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt
index 6fb114baf..10a9dc93d 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt
@@ -5,6 +5,7 @@ import app.revanced.patcher.patch.annotations.RequiresIntegrations
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch
import app.revanced.patches.youtube.misc.integrations.annotations.IntegrationsCompatibility
import app.revanced.patches.youtube.misc.integrations.fingerprints.InitFingerprint
+import app.revanced.patches.youtube.misc.integrations.fingerprints.EmbeddedPlayerControlsOverlayFingerprint
import app.revanced.patches.youtube.misc.integrations.fingerprints.ServiceFingerprint
import app.revanced.patches.youtube.misc.integrations.fingerprints.StandalonePlayerFingerprint
@@ -13,5 +14,5 @@ import app.revanced.patches.youtube.misc.integrations.fingerprints.StandalonePla
@RequiresIntegrations
class IntegrationsPatch : AbstractIntegrationsPatch(
"Lapp/revanced/integrations/utils/ReVancedUtils;",
- listOf(InitFingerprint, StandalonePlayerFingerprint, ServiceFingerprint),
+ listOf(InitFingerprint, StandalonePlayerFingerprint, ServiceFingerprint, EmbeddedPlayerControlsOverlayFingerprint),
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/annotations/OpenLinksExternallyCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/annotations/OpenLinksExternallyCompatibility.kt
index 91a2724c6..9485b3efc 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/annotations/OpenLinksExternallyCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/annotations/OpenLinksExternallyCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.misc.links.open.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class OpenLinksExternallyCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/fingerprints/BindSessionServiceFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/fingerprints/BindSessionServiceFingerprint.kt
index f7b41a242..b1d108279 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/fingerprints/BindSessionServiceFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/fingerprints/BindSessionServiceFingerprint.kt
@@ -7,7 +7,7 @@ import org.jf.dexlib2.Opcode
object BindSessionServiceFingerprint : MethodFingerprint(
returnType = "L",
- access = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
opcodes = listOf(
Opcode.IPUT_OBJECT,
Opcode.NEW_INSTANCE,
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/fingerprints/GetCustomTabPackageNameFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/fingerprints/GetCustomTabPackageNameFingerprint.kt
index ffacf0355..78b795566 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/fingerprints/GetCustomTabPackageNameFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/fingerprints/GetCustomTabPackageNameFingerprint.kt
@@ -7,7 +7,7 @@ import org.jf.dexlib2.Opcode
object GetCustomTabPackageNameFingerprint : MethodFingerprint(
returnType = "L",
- access = AccessFlags.PUBLIC or AccessFlags.STATIC,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
opcodes = listOf(
Opcode.CHECK_CAST,
Opcode.NEW_INSTANCE,
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/fingerprints/InitializeCustomTabSupportFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/fingerprints/InitializeCustomTabSupportFingerprint.kt
index 0901efbbd..b9f80a60b 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/fingerprints/InitializeCustomTabSupportFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/fingerprints/InitializeCustomTabSupportFingerprint.kt
@@ -7,7 +7,7 @@ import org.jf.dexlib2.Opcode
object InitializeCustomTabSupportFingerprint : MethodFingerprint(
returnType = "V",
- access = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
opcodes = listOf(
Opcode.CHECK_CAST,
Opcode.NEW_INSTANCE,
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/patch/OpenLinksExternallyPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/patch/OpenLinksExternallyPatch.kt
index ec2e2b5fa..64750c53c 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/patch/OpenLinksExternallyPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/links/open/patch/OpenLinksExternallyPatch.kt
@@ -34,11 +34,10 @@ class OpenLinksExternallyPatch : BytecodePatch(
override fun execute(context: BytecodeContext): PatchResult {
SettingsPatch.PreferenceScreen.MISC.addPreferences(
SwitchPreference(
- "revanced_enable_external_browser",
- StringResource("revanced_enable_external_browser_title", "Open links in browser"),
- true,
- StringResource("revanced_enable_external_browser_summary_on", "Opening links externally"),
- StringResource("revanced_enable_external_browser_summary_off", "Opening links in app")
+ "revanced_external_browser",
+ StringResource("revanced_external_browser_title", "Open links in browser"),
+ StringResource("revanced_external_browser_summary_on", "Opening links externally"),
+ StringResource("revanced_external_browser_summary_off", "Opening links in app")
)
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/annotation/LithoFilterCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/annotation/LithoFilterCompatibility.kt
index 6a55da3b2..7d483d276 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/annotation/LithoFilterCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/annotation/LithoFilterCompatibility.kt
@@ -3,23 +3,7 @@ package app.revanced.patches.youtube.misc.litho.filter.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class LithoFilterCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ProtobufBufferFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ProtobufBufferFingerprint.kt
new file mode 100644
index 000000000..9e0997936
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ProtobufBufferFingerprint.kt
@@ -0,0 +1,25 @@
+package app.revanced.patches.youtube.misc.litho.filter.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import org.jf.dexlib2.Opcode
+
+object ProtobufBufferFingerprint : MethodFingerprint(
+ opcodes = listOf(
+ Opcode.IGET_OBJECT, // References the field required below.
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ Opcode.IF_NEZ,
+ Opcode.CONST_4,
+ Opcode.GOTO,
+ Opcode.CHECK_CAST, // Casts the referenced field to a specific type that stores the protobuf buffer.
+ Opcode.INVOKE_VIRTUAL
+ )
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/patch/LithoFilterPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/patch/LithoFilterPatch.kt
index f5174c190..84c53504c 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/patch/LithoFilterPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/patch/LithoFilterPatch.kt
@@ -17,6 +17,7 @@ import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.litho.filter.annotation.LithoFilterCompatibility
import app.revanced.patches.youtube.misc.litho.filter.fingerprints.ComponentContextParserFingerprint
import app.revanced.patches.youtube.misc.litho.filter.fingerprints.EmptyComponentBuilderFingerprint
+import app.revanced.patches.youtube.misc.litho.filter.fingerprints.ProtobufBufferFingerprint
import app.revanced.patches.youtube.misc.litho.filter.fingerprints.ReadComponentIdentifierFingerprint
import org.jf.dexlib2.iface.instruction.Instruction
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@@ -32,7 +33,9 @@ class LithoFilterPatch : BytecodePatch(
) {
override fun execute(context: BytecodeContext): PatchResult {
ComponentContextParserFingerprint.result?.also {
- arrayOf(EmptyComponentBuilderFingerprint, ReadComponentIdentifierFingerprint).forEach { fingerprint ->
+ arrayOf(
+ EmptyComponentBuilderFingerprint, ReadComponentIdentifierFingerprint, ProtobufBufferFingerprint
+ ).forEach { fingerprint ->
if (!fingerprint.resolve(context, it.mutableMethod, it.mutableClass))
return fingerprint.toErrorResult()
}
@@ -45,26 +48,54 @@ class LithoFilterPatch : BytecodePatch(
val builderMethodDescriptor = instruction(builderMethodIndex).descriptor
val emptyComponentFieldDescriptor = instruction(emptyComponentFieldIndex).descriptor
// Register is overwritten right after it is used in this patch, therefore free to clobber.
- val clobberedRegister = instruction(insertHookIndex - 1).twoRegisterA
+ val free = instruction(insertHookIndex - 1).registerA
+ val free2 = instruction(insertHookIndex).registerA
@Suppress("UnnecessaryVariable")
// The register, this patch clobbers, is previously used for the StringBuilder,
// later on a new StringBuilder is instantiated on it.
- val stringBuilderRegister = clobberedRegister
+ val stringBuilderRegister = free
- val identifierRegister = instruction(ReadComponentIdentifierFingerprint.patternScanEndIndex).oneRegisterA
+ val identifierRegister =
+ instruction(ReadComponentIdentifierFingerprint.patternScanEndIndex).registerA
+
+ // Parameter that holds a ref to a type with a field that ref the protobuf buffer object.
+ val protobufParameterNumber = 3
+
+ // Get the field that stores an protobuf buffer required below.
+ val protobufBufferRefTypeRefFieldDescriptor =
+ instruction(ProtobufBufferFingerprint.patternScanStartIndex).descriptor
+ val protobufBufferRefTypeDescriptor =
+ instruction(ProtobufBufferFingerprint.patternScanEndIndex - 1).descriptor
+ val protobufBufferFieldDescriptor = "$protobufBufferRefTypeDescriptor->b:Ljava/nio/ByteBuffer;"
addInstructions(
- insertHookIndex, // right after setting the component.pathBuilder field,
+ insertHookIndex, // right after setting the component.pathBuilder field.
"""
- invoke-static {v$stringBuilderRegister, v$identifierRegister}, Lapp/revanced/integrations/patches/LithoFilterPatch;->filter(Ljava/lang/StringBuilder;Ljava/lang/String;)Z
- move-result v$clobberedRegister
- if-eqz v$clobberedRegister, :not_an_ad
- move-object/from16 v$clobberedRegister, p1
- invoke-static {v$clobberedRegister}, $builderMethodDescriptor
- move-result-object v$clobberedRegister
- iget-object v$clobberedRegister, v$clobberedRegister, $emptyComponentFieldDescriptor
- return-object v$clobberedRegister
+ # Get the protobuf buffer object.
+
+ move-object/from16 v$free2, p$protobufParameterNumber
+ iget-object v$free2, v$free2, $protobufBufferRefTypeRefFieldDescriptor
+ check-cast v$free2, $protobufBufferRefTypeDescriptor
+
+ # Register "free" now holds the protobuf buffer object
+
+ iget-object v$free2, v$free2, $protobufBufferFieldDescriptor
+
+ # Invoke the filter method.
+
+ invoke-static { v$stringBuilderRegister, v$identifierRegister, v$free2 }, $FILTER_METHOD_DESCRIPTOR
+ move-result v$free
+
+ if-eqz v$free, :not_an_ad
+
+ # If the filter method returned true, then return a replacement empty component.
+
+ move-object/from16 v$free, p1
+ invoke-static {v$free}, $builderMethodDescriptor
+ move-result-object v$free
+ iget-object v$free, v$free, $emptyComponentFieldDescriptor
+ return-object v$free
""",
listOf(ExternalLabel("not_an_ad", instruction(insertHookIndex)))
)
@@ -75,16 +106,20 @@ class LithoFilterPatch : BytecodePatch(
}
private companion object {
+ private val MethodFingerprint.patternScanResult
+ get() = result!!.scanResult.patternScanResult!!
+
val MethodFingerprint.patternScanEndIndex
- get() = result!!.scanResult.patternScanResult!!.endIndex
+ get() = patternScanResult.endIndex
+
+ val MethodFingerprint.patternScanStartIndex
+ get() = patternScanResult.startIndex
val Instruction.descriptor
get() = (this as ReferenceInstruction).reference.toString()
- val Instruction.oneRegisterA
- get() = (this as OneRegisterInstruction).registerA
-
- val Instruction.twoRegisterA
- get() = (this as TwoRegisterInstruction).registerA
+ const val FILTER_METHOD_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/components/LithoFilterPatch;" +
+ "->filter(Ljava/lang/StringBuilder;Ljava/lang/String;Ljava/nio/ByteBuffer;)Z"
}
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/annotations/MicroGPatchCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/annotations/MicroGPatchCompatibility.kt
index 101098dba..352ed3746 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/annotations/MicroGPatchCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/annotations/MicroGPatchCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.misc.microg.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class MicroGPatchCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/bytecode/MicroGBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/bytecode/MicroGBytecodePatch.kt
index 9a5926896..68bb5e91b 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/bytecode/MicroGBytecodePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/bytecode/MicroGBytecodePatch.kt
@@ -10,9 +10,8 @@ import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.fingerprints.WatchWhileActivityFingerprint
-import app.revanced.patches.shared.misc.fix.spoof.patch.ClientSpoofPatch
import app.revanced.patches.youtube.layout.buttons.cast.patch.HideCastButtonPatch
-import app.revanced.patches.youtube.misc.fix.playback.patch.SpoofSignatureVerificationPatch
+import app.revanced.patches.youtube.misc.fix.playback.patch.ClientSpoofPatch
import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility
import app.revanced.patches.youtube.misc.microg.fingerprints.*
import app.revanced.patches.youtube.misc.microg.patch.resource.MicroGResourcePatch
@@ -25,6 +24,7 @@ import app.revanced.util.microg.MicroGBytecodeHelper
[
MicroGResourcePatch::class,
HideCastButtonPatch::class,
+ ClientSpoofPatch::class
]
)
@Name("vanced-microg-support")
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/MicroGResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/MicroGResourcePatch.kt
index 257f779e2..51e6d5827 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/MicroGResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/MicroGResourcePatch.kt
@@ -32,8 +32,8 @@ class MicroGResourcePatch : ResourcePatch {
SettingsPatch.addPreference(
Preference(
StringResource("microg_settings", "MicroG Settings"),
- Preference.Intent("$MICROG_VENDOR.android.gms", "", "org.microg.gms.ui.SettingsActivity"),
StringResource("microg_settings_summary", "Settings for MicroG"),
+ Preference.Intent("$MICROG_VENDOR.android.gms", "", "org.microg.gms.ui.SettingsActivity")
)
)
SettingsPatch.renameIntentsTargetPackage(REVANCED_PACKAGE_NAME)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt
index 6a59fbcc1..88bff32b0 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.misc.minimizedplayback.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class MinimizedPlaybackCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/fingerprints/KidsMinimizedPlaybackPolicyControllerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/fingerprints/KidsMinimizedPlaybackPolicyControllerFingerprint.kt
index 9a9f629bd..9763d18d3 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/fingerprints/KidsMinimizedPlaybackPolicyControllerFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/fingerprints/KidsMinimizedPlaybackPolicyControllerFingerprint.kt
@@ -7,7 +7,7 @@ import org.jf.dexlib2.Opcode
object KidsMinimizedPlaybackPolicyControllerFingerprint : MethodFingerprint(
returnType = "V",
- access = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("I", "L", "L"),
opcodes = listOf(
Opcode.IF_EQZ,
@@ -19,5 +19,7 @@ object KidsMinimizedPlaybackPolicyControllerFingerprint : MethodFingerprint(
Opcode.IGET,
Opcode.INVOKE_STATIC
),
- customFingerprint = { it.definingClass.endsWith("MinimizedPlaybackPolicyController;") }
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass.endsWith("MinimizedPlaybackPolicyController;")
+ }
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/patch/MinimizedPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/patch/MinimizedPlaybackPatch.kt
index ee2ad6f25..ba8d9be8d 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/patch/MinimizedPlaybackPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/patch/MinimizedPlaybackPatch.kt
@@ -44,7 +44,7 @@ class MinimizedPlaybackPatch : BytecodePatch(
SettingsPatch.PreferenceScreen.MISC.addPreferences(
NonInteractivePreference(
StringResource("revanced_minimized_playback_enabled_title", "Minimized playback"),
- StringResource("revanced_minimized_playback_summary_on", "This setting can be found in Settings -> General")
+ StringResource("revanced_minimized_playback_summary_on", "This setting can be found in Settings -> Background")
)
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/annotation/PlayerControlsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/annotation/PlayerControlsCompatibility.kt
index 15b40d0ea..296b6477b 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/annotation/PlayerControlsCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/annotation/PlayerControlsCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.misc.playercontrols.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class PlayerControlsCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/BottomControlsInflateFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/BottomControlsInflateFingerprint.kt
index 9df6bcf0c..902f88943 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/BottomControlsInflateFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/BottomControlsInflateFingerprint.kt
@@ -12,7 +12,7 @@ object BottomControlsInflateFingerprint : MethodFingerprint(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT
),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.implementation?.instructions?.any { instruction ->
instruction.opcode.ordinal == Opcode.CONST.ordinal &&
(instruction as? WideLiteralInstruction)?.wideLiteral == PlayerControlsBytecodePatch.bottomUiContainerResourceId
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/PlayerControlsVisibilityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/PlayerControlsVisibilityFingerprint.kt
index 91e0acb01..0bf59e705 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/PlayerControlsVisibilityFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/PlayerControlsVisibilityFingerprint.kt
@@ -6,7 +6,7 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object PlayerControlsVisibilityFingerprint : MethodFingerprint(
"V",
parameters = listOf("Z", "Z"),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("YouTubeControlsOverlay;")
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/annotation/PlayerOverlaysHookCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/annotation/PlayerOverlaysHookCompatibility.kt
index ca85a8986..89a6fa3d4 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/annotation/PlayerOverlaysHookCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/annotation/PlayerOverlaysHookCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.misc.playeroverlay.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class PlayerOverlaysHookCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/fingerprint/PlayerOverlaysOnFinishInflateFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/fingerprint/PlayerOverlaysOnFinishInflateFingerprint.kt
index 1defdfe65..1317e14dc 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/fingerprint/PlayerOverlaysOnFinishInflateFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/fingerprint/PlayerOverlaysOnFinishInflateFingerprint.kt
@@ -4,7 +4,7 @@ package app.revanced.patches.youtube.misc.playeroverlay.fingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object PlayerOverlaysOnFinishInflateFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("YouTubePlayerOverlaysLayout;") && methodDef.name == "onFinishInflate"
}
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/annotation/PlayerTypeHookCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/annotation/PlayerTypeHookCompatibility.kt
index 4a3244cdd..dff4ca516 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/annotation/PlayerTypeHookCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/annotation/PlayerTypeHookCompatibility.kt
@@ -3,22 +3,6 @@ package app.revanced.patches.youtube.misc.playertype.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class PlayerTypeHookCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/fingerprint/UpdatePlayerTypeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/fingerprint/PlayerTypeFingerprint.kt
similarity index 72%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/playertype/fingerprint/UpdatePlayerTypeFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/misc/playertype/fingerprint/PlayerTypeFingerprint.kt
index 0eb8e9a11..c6588b82f 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/fingerprint/UpdatePlayerTypeFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/fingerprint/PlayerTypeFingerprint.kt
@@ -1,15 +1,14 @@
package app.revanced.patches.youtube.misc.playertype.fingerprint
import app.revanced.patcher.extensions.or
-import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
-@FuzzyPatternScanMethod(2)
-object UpdatePlayerTypeFingerprint : MethodFingerprint(
- "V",
- AccessFlags.PUBLIC or AccessFlags.FINAL,
+object PlayerTypeFingerprint : MethodFingerprint(
+ returnType = "V",
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ parameters = listOf("L"),
opcodes = listOf(
Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT,
@@ -29,5 +28,8 @@ object UpdatePlayerTypeFingerprint : MethodFingerprint(
Opcode.INVOKE_STATIC,
Opcode.INVOKE_VIRTUAL,
Opcode.RETURN_VOID
- )
+ ),
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass.endsWith("YouTubePlayerOverlaysLayout;")
+ }
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/fingerprint/VideoStateFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/fingerprint/VideoStateFingerprint.kt
new file mode 100644
index 000000000..259915bca
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/fingerprint/VideoStateFingerprint.kt
@@ -0,0 +1,24 @@
+package app.revanced.patches.youtube.misc.playertype.fingerprint
+
+import app.revanced.patcher.extensions.or
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import org.jf.dexlib2.AccessFlags
+import org.jf.dexlib2.Opcode
+
+object VideoStateFingerprint : MethodFingerprint(
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ returnType = "V",
+ parameters = listOf("L"),
+ opcodes = listOf(
+ Opcode.IGET_OBJECT,
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.IGET_OBJECT,
+ Opcode.CONST_4,
+ Opcode.IF_EQZ,
+ Opcode.IF_EQZ,
+ Opcode.IGET_OBJECT, // obfuscated parameter field name
+ ),
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass.endsWith("YouTubeControlsOverlay;")
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/patch/PlayerTypeHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/patch/PlayerTypeHookPatch.kt
index 75e722072..999356376 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/patch/PlayerTypeHookPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/patch/PlayerTypeHookPatch.kt
@@ -1,34 +1,61 @@
package app.revanced.patches.youtube.misc.playertype.patch
+import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstruction
+import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.playertype.annotation.PlayerTypeHookCompatibility
-import app.revanced.patches.youtube.misc.playertype.fingerprint.UpdatePlayerTypeFingerprint
+import app.revanced.patches.youtube.misc.playertype.fingerprint.PlayerTypeFingerprint
+import app.revanced.patches.youtube.misc.playertype.fingerprint.VideoStateFingerprint
+import org.jf.dexlib2.iface.instruction.ReferenceInstruction
@Name("player-type-hook")
-@Description("Hook to get the current player type of WatchWhileActivity")
+@Description("Hook to get the current player type and video playback state.")
@PlayerTypeHookCompatibility
@Version("0.0.1")
@DependsOn([IntegrationsPatch::class])
class PlayerTypeHookPatch : BytecodePatch(
- listOf(
- UpdatePlayerTypeFingerprint
- )
+ listOf(PlayerTypeFingerprint, VideoStateFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
- // hook YouTubePlayerOverlaysLayout.updatePlayerLayout()
- UpdatePlayerTypeFingerprint.result!!.mutableMethod.addInstruction(
- 0,
- "invoke-static { p1 }, Lapp/revanced/integrations/patches/PlayerTypeHookPatch;->YouTubePlayerOverlaysLayout_updatePlayerTypeHookEX(Ljava/lang/Object;)V"
- )
+
+ PlayerTypeFingerprint.result?.let {
+ it.mutableMethod.apply {
+ addInstruction(
+ 0,
+ "invoke-static {p1}, $INTEGRATIONS_CLASS_DESCRIPTOR->setPlayerType(Ljava/lang/Enum;)V"
+ )
+ }
+ } ?: return PlayerTypeFingerprint.toErrorResult()
+
+ VideoStateFingerprint.result?.let {
+ it.mutableMethod.apply {
+ val endIndex = it.scanResult.patternScanResult!!.endIndex
+ val videoStateFieldName = instruction(endIndex).reference
+ addInstructions(
+ 0, """
+ iget-object v0, p1, $videoStateFieldName # copy VideoState parameter field
+ invoke-static {v0}, $INTEGRATIONS_CLASS_DESCRIPTOR->setVideoState(Ljava/lang/Enum;)V
+ """
+ )
+ }
+ } ?: return VideoStateFingerprint.toErrorResult()
+
return PatchResultSuccess()
}
+
+ companion object {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR =
+ "Lapp/revanced/integrations/patches/PlayerTypeHookPatch;"
+ }
+
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/LicenseActivityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/LicenseActivityFingerprint.kt
index 11395105f..42a9f0afa 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/LicenseActivityFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/LicenseActivityFingerprint.kt
@@ -3,7 +3,7 @@ package app.revanced.patches.youtube.misc.settings.bytecode.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object LicenseActivityFingerprint : MethodFingerprint(
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("LicenseActivity;") && methodDef.name == "onCreate"
}
)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/SetThemeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/SetThemeFingerprint.kt
new file mode 100644
index 000000000..468e8e244
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/SetThemeFingerprint.kt
@@ -0,0 +1,20 @@
+package app.revanced.patches.youtube.misc.settings.bytecode.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourcePatch
+import org.jf.dexlib2.Opcode
+import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
+
+object SetThemeFingerprint : MethodFingerprint(
+ returnType = "L",
+ opcodes = listOf(Opcode.RETURN_OBJECT),
+ customFingerprint = { methodDef, _ ->
+ methodDef.implementation?.instructions?.any { instruction ->
+ if (instruction.opcode != Opcode.CONST) return@any false
+
+ val wideLiteral = (instruction as WideLiteralInstruction).wideLiteral
+
+ SettingsResourcePatch.appearanceStringId == wideLiteral
+ } ?: false
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/ThemeSetterAppFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/ThemeSetterAppFingerprint.kt
deleted file mode 100644
index 1fceecd38..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/ThemeSetterAppFingerprint.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package app.revanced.patches.youtube.misc.settings.bytecode.fingerprints
-
-import app.revanced.patcher.extensions.or
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import org.jf.dexlib2.AccessFlags
-import org.jf.dexlib2.Opcode
-
-object ThemeSetterAppFingerprint : MethodFingerprint(
- "L",
- AccessFlags.PUBLIC or AccessFlags.STATIC,
- parameters = listOf("L", "L", "L", "L"),
- opcodes = listOf(
- Opcode.CONST, // target reference
- Opcode.GOTO,
- Opcode.CONST, // target reference
- Opcode.INVOKE_DIRECT,
- Opcode.RETURN_OBJECT,
- Opcode.NEW_INSTANCE,
- null, // changed from invoke interface to invoke virtual
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.SGET_OBJECT,
- Opcode.IF_NE,
- Opcode.CONST, // target reference
- )
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/ThemeSetterSystemFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/ThemeSetterSystemFingerprint.kt
deleted file mode 100644
index d57892735..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/ThemeSetterSystemFingerprint.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package app.revanced.patches.youtube.misc.settings.bytecode.fingerprints
-
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourcePatch
-import org.jf.dexlib2.Opcode
-import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
-
-object ThemeSetterSystemFingerprint : MethodFingerprint(
- "L",
- opcodes = listOf(Opcode.RETURN_OBJECT),
- customFingerprint = { methodDef ->
- methodDef.implementation?.instructions?.any {
- it.opcode.ordinal == Opcode.CONST.ordinal && (it as WideLiteralInstruction).wideLiteral == SettingsResourcePatch.appearanceStringId
- } == true
- }
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/patch/SettingsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/patch/SettingsPatch.kt
index 331389068..8804f02c5 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/patch/SettingsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/patch/SettingsPatch.kt
@@ -7,6 +7,8 @@ import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.extensions.instruction
+import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
@@ -15,78 +17,61 @@ import app.revanced.patches.shared.settings.preference.impl.Preference
import app.revanced.patches.shared.settings.util.AbstractPreferenceScreen
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.LicenseActivityFingerprint
-import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.ThemeSetterAppFingerprint
-import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.ThemeSetterSystemFingerprint
+import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.SetThemeFingerprint
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourcePatch
+import org.jf.dexlib2.Opcode
+import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.util.MethodUtil
-@DependsOn(
- [
- IntegrationsPatch::class,
- SettingsResourcePatch::class,
- ]
-)
+@DependsOn([IntegrationsPatch::class, SettingsResourcePatch::class, ])
@Name("settings")
@Description("Adds settings for ReVanced to YouTube.")
@Version("0.0.1")
class SettingsPatch : BytecodePatch(
- listOf(LicenseActivityFingerprint, ThemeSetterSystemFingerprint, ThemeSetterAppFingerprint)
+ listOf(LicenseActivityFingerprint, SetThemeFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
- fun buildInvokeInstructionsString(
+ // TODO: Remove this when it is only required at one place.
+ fun getSetThemeInstructionString(
registers: String = "v0",
classDescriptor: String = THEME_HELPER_DESCRIPTOR,
methodName: String = SET_THEME_METHOD_NAME,
parameters: String = "Ljava/lang/Object;"
- ) = "invoke-static {$registers}, $classDescriptor->$methodName($parameters)V"
+ ) = "invoke-static { $registers }, $classDescriptor->$methodName($parameters)V"
- // apply the current theme of the settings page
- ThemeSetterSystemFingerprint.result!!.let { result ->
- val call = buildInvokeInstructionsString()
- result.mutableMethod.apply {
- addInstruction(
- result.scanResult.patternScanResult!!.startIndex, call
- )
- addInstructions(
- implementation!!.instructions.size - 1, call
- )
- }
- }
+ SetThemeFingerprint.result?.mutableMethod?.let { setThemeMethod ->
+ setThemeMethod.implementation!!.instructions.mapIndexedNotNull { i, instruction ->
+ if (instruction.opcode == Opcode.RETURN_OBJECT) i else null
+ }
+ .asReversed() // Prevent index shifting.
+ .forEach { returnIndex ->
+ // The following strategy is to replace the return instruction with the setTheme instruction,
+ // then add a return instruction after the setTheme instruction.
+ // This is done because the return instruction is a target of another instruction.
- // set the theme based on the preference of the app
- ThemeSetterAppFingerprint.result?.apply {
- fun buildInstructionsString(theme: Int) = """
- const/4 v0, 0x$theme
- ${buildInvokeInstructionsString(parameters = "I")}
- """
+ setThemeMethod.apply {
+ // This register is returned by the setTheme method.
+ val register = instruction(returnIndex).registerA
- val patternScanResult = scanResult.patternScanResult!!
+ val setThemeInstruction = getSetThemeInstructionString("v$register")
+ replaceInstruction(returnIndex, setThemeInstruction)
+ addInstruction(returnIndex + 1, "return-object v0")
+ }
+ }
+ } ?: return SetThemeFingerprint.toErrorResult()
- mutableMethod.apply {
- addInstructions(
- patternScanResult.endIndex + 1, buildInstructionsString(1)
- )
- addInstructions(
- patternScanResult.endIndex - 7, buildInstructionsString(0)
- )
- addInstructions(
- patternScanResult.endIndex - 9, buildInstructionsString(1)
- )
- addInstructions(
- implementation!!.instructions.size - 2, buildInstructionsString(0)
- )
- }
- } ?: return ThemeSetterAppFingerprint.toErrorResult()
- // set the theme based on the preference of the device
+ // Modify the license activity and remove all existing layout code.
+ // Must modify an existing activity and cannot add a new activity to the manifest,
+ // as that fails for root installations.
LicenseActivityFingerprint.result!!.apply licenseActivity@{
mutableMethod.apply {
fun buildSettingsActivityInvokeString(
registers: String = "p0",
classDescriptor: String = SETTINGS_ACTIVITY_DESCRIPTOR,
methodName: String = "initializeSettings",
- parameters: String = this@licenseActivity.mutableClass.type
- ) = buildInvokeInstructionsString(registers, classDescriptor, methodName, parameters)
+ parameters: String = "Landroid/app/Activity;"
+ ) = getSetThemeInstructionString(registers, classDescriptor, methodName, parameters)
// initialize the settings
addInstructions(
@@ -95,9 +80,6 @@ class SettingsPatch : BytecodePatch(
return-void
"""
)
-
- // set the current theme
- addInstruction(0, buildSettingsActivityInvokeString(methodName = "setTheme"))
}
// remove method overrides
@@ -106,14 +88,13 @@ class SettingsPatch : BytecodePatch(
}
}
+
return PatchResultSuccess()
}
internal companion object {
private const val INTEGRATIONS_PACKAGE = "app/revanced/integrations"
-
private const val SETTINGS_ACTIVITY_DESCRIPTOR = "L$INTEGRATIONS_PACKAGE/settingsmenu/ReVancedSettingActivity;"
-
private const val THEME_HELPER_DESCRIPTOR = "L$INTEGRATIONS_PACKAGE/utils/ThemeHelper;"
private const val SET_THEME_METHOD_NAME = "setTheme"
@@ -128,6 +109,15 @@ class SettingsPatch : BytecodePatch(
fun renameIntentsTargetPackage(newPackage: String) {
SettingsResourcePatch.overrideIntentsTargetPackage = newPackage
}
+
+ /**
+ * Creates an intent to open ReVanced settings of the given name
+ */
+ fun createReVancedSettingsIntent(settingsName: String) = Preference.Intent(
+ "com.google.android.youtube",
+ settingsName,
+ "com.google.android.libraries.social.licenses.LicenseActivity"
+ )
}
/**
@@ -137,6 +127,7 @@ class SettingsPatch : BytecodePatch(
val ADS = Screen("ads", "Ads", "Ad related settings")
val INTERACTIONS = Screen("interactions", "Interaction", "Settings related to interactions")
val LAYOUT = Screen("layout", "Layout", "Settings related to the layout")
+ val VIDEO = Screen("video", "Video", "Settings related to the video player")
val MISC = Screen("misc", "Misc", "Miscellaneous patches")
override fun commit(screen: app.revanced.patches.shared.settings.preference.impl.PreferenceScreen) {
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/resource/patch/SettingsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/resource/patch/SettingsResourcePatch.kt
index 4248b6778..86665f511 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/resource/patch/SettingsResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/resource/patch/SettingsResourcePatch.kt
@@ -10,15 +10,13 @@ import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.addPreference
-import app.revanced.patches.shared.settings.preference.impl.ArrayResource
-import app.revanced.patches.shared.settings.preference.impl.Preference
-import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
-import app.revanced.patches.shared.settings.preference.impl.StringResource
+import app.revanced.patches.shared.settings.preference.impl.*
import app.revanced.patches.shared.settings.resource.patch.AbstractSettingsResourcePatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources
import app.revanced.util.resources.ResourceUtils.mergeStrings
+import org.w3c.dom.Element
import org.w3c.dom.Node
@Name("settings-resource-patch")
@@ -32,49 +30,66 @@ class SettingsResourcePatch : AbstractSettingsResourcePatch(
override fun execute(context: ResourceContext): PatchResult {
super.execute(context)
- /*
- * used by a fingerprint of SettingsPatch
- */
+ // Used for a fingerprint from SettingsPatch.
appearanceStringId = ResourceMappingPatch.resourceMappings.find {
it.type == "string" && it.name == "app_theme_appearance_dark"
}!!.id
- /*
- * create missing directory for the resources
- */
- context["res/drawable-ldrtl-xxxhdpi"].mkdirs()
-
/*
* copy layout resources
*/
arrayOf(
- ResourceUtils.ResourceGroup(
- "layout",
- "revanced_settings_toolbar.xml",
- "revanced_settings_with_toolbar.xml",
- "revanced_settings_with_toolbar_layout.xml"
- ), ResourceUtils.ResourceGroup(
- // required resource for back button, because when the base APK is used, this resource will not exist
- "drawable-xxxhdpi", "quantum_ic_arrow_back_white_24.png"
- ), ResourceUtils.ResourceGroup(
- // required resource for back button, because when the base APK is used, this resource will not exist
- "drawable-ldrtl-xxxhdpi", "quantum_ic_arrow_back_white_24.png"
- )
+ ResourceUtils.ResourceGroup("layout", "revanced_settings_with_toolbar.xml")
).forEach { resourceGroup ->
context.copyResources("settings", resourceGroup)
}
preferencesEditor = context.xmlEditor["res/xml/settings_fragment.xml"]
+ // Modify the manifest and add an data intent filter to the LicenseActivity.
+ // Some devices freak out if undeclared data is passed to an intent,
+ // and this change appears to fix the issue.
+ context.xmlEditor["AndroidManifest.xml"].use { editor ->
+ // An xml regular expression would probably work better than this manual searching.
+ val manifestNodes = editor.file.getElementsByTagName("manifest").item(0).childNodes
+ for (i in 0..manifestNodes.length) {
+ val node = manifestNodes.item(i)
+ if (node != null && node.nodeName == "application") {
+ val applicationNodes = node.childNodes
+ for (j in 0..applicationNodes.length) {
+ val applicationChild = applicationNodes.item(j)
+ if (applicationChild is Element && applicationChild.nodeName == "activity"
+ && applicationChild.getAttribute("android:name") == "com.google.android.libraries.social.licenses.LicenseActivity"
+ ) {
+ val intentFilter = editor.file.createElement("intent-filter")
+ val mimeType = editor.file.createElement("data")
+ mimeType.setAttribute("android:mimeType", "text/plain")
+ intentFilter.appendChild(mimeType)
+ applicationChild.appendChild(intentFilter)
+ break
+ }
+ }
+ }
+ }
+ }
+
+
// Add the ReVanced settings to the YouTube settings
- val youtubePackage = "com.google.android.youtube"
SettingsPatch.addPreference(
Preference(
StringResource("revanced_settings", "ReVanced"),
- Preference.Intent(
- youtubePackage, "revanced_settings", "com.google.android.libraries.social.licenses.LicenseActivity"
- ),
StringResource("revanced_settings_summary", "ReVanced specific settings"),
+ SettingsPatch.createReVancedSettingsIntent("revanced_settings")
+ )
+ )
+
+ SettingsPatch.PreferenceScreen.MISC.addPreferences(
+ TextPreference(
+ key = null,
+ title = StringResource("revanced_pref_import_export_title", "Import / Export"),
+ summary = StringResource("revanced_pref_import_export_summary", "Import / Export ReVanced settings"),
+ inputType = InputType.TEXT_MULTI_LINE,
+ tag = "app.revanced.integrations.settingsmenu.ImportExportPreference"
)
)
@@ -85,11 +100,8 @@ class SettingsResourcePatch : AbstractSettingsResourcePatch(
internal companion object {
- // Used by a fingerprint of SettingsPatch
- // this field is located in the SettingsResourcePatch
- // because if it were to be defined in the SettingsPatch companion object,
- // the companion object could be initialized before ResourceMappingResourcePatch has executed.
- internal var appearanceStringId: Long = -1
+ // Used for a fingerprint from SettingsPatch.
+ internal var appearanceStringId = -1L
// if this is not null, all intents will be renamed to this
var overrideIntentsTargetPackage: String? = null
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/annotations/CustomPlaybackSpeedCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/annotations/CustomPlaybackSpeedCompatibility.kt
deleted file mode 100644
index eae4e1c02..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/annotations/CustomPlaybackSpeedCompatibility.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package app.revanced.patches.youtube.misc.video.speed.custom.annotations
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class CustomPlaybackSpeedCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/VideoSpeedPatchFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/VideoSpeedPatchFingerprint.kt
deleted file mode 100644
index 541601fd1..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/VideoSpeedPatchFingerprint.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package app.revanced.patches.youtube.misc.video.speed.custom.fingerprints
-
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import org.jf.dexlib2.Opcode
-
-object VideoSpeedPatchFingerprint : MethodFingerprint(
- opcodes = listOf(Opcode.FILL_ARRAY_DATA),
- customFingerprint = { methodDef ->
- methodDef.definingClass.endsWith("CustomVideoSpeedPatch;") && methodDef.name == ""
- }
-)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/patch/CustomVideoSpeedPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/patch/CustomVideoSpeedPatch.kt
deleted file mode 100644
index c038ba497..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/patch/CustomVideoSpeedPatch.kt
+++ /dev/null
@@ -1,195 +0,0 @@
-package app.revanced.patches.youtube.misc.video.speed.custom.patch
-
-import app.revanced.patcher.annotation.Description
-import app.revanced.patcher.annotation.Name
-import app.revanced.patcher.annotation.Version
-import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.extensions.addInstructions
-import app.revanced.patcher.extensions.replaceInstruction
-import app.revanced.patcher.patch.*
-import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.video.speed.custom.annotations.CustomPlaybackSpeedCompatibility
-import app.revanced.patches.youtube.misc.video.speed.custom.fingerprints.SpeedArrayGeneratorFingerprint
-import app.revanced.patches.youtube.misc.video.speed.custom.fingerprints.SpeedLimiterFingerprint
-import app.revanced.patches.youtube.misc.video.speed.custom.fingerprints.VideoSpeedPatchFingerprint
-import org.jf.dexlib2.builder.instruction.BuilderArrayPayload
-import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
-import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
-import org.jf.dexlib2.iface.instruction.ReferenceInstruction
-import org.jf.dexlib2.iface.reference.FieldReference
-import org.jf.dexlib2.iface.reference.MethodReference
-import java.util.stream.DoubleStream
-import kotlin.math.roundToInt
-
-@Patch
-@Name("custom-video-speed")
-@Description("Adds more video speed options.")
-@DependsOn([IntegrationsPatch::class])
-@CustomPlaybackSpeedCompatibility
-@Version("0.0.1")
-class CustomVideoSpeedPatch : BytecodePatch(
- listOf(
- SpeedArrayGeneratorFingerprint, SpeedLimiterFingerprint, VideoSpeedPatchFingerprint
- )
-) {
-
- override fun execute(context: BytecodeContext): PatchResult {
- val speedLimitMin = minVideoSpeed!!.toFloat()
- val speedLimitMax = maxVideoSpeed!!.toFloat().coerceAtLeast(speedLimitMin)
- val speedsGranularity = videoSpeedsGranularity!!.toFloat()
-
- val arrayGenMethod = SpeedArrayGeneratorFingerprint.result?.mutableMethod!!
- val arrayGenMethodImpl = arrayGenMethod.implementation!!
-
- val sizeCallIndex = arrayGenMethodImpl.instructions
- .indexOfFirst { ((it as? ReferenceInstruction)?.reference as? MethodReference)?.name == "size" }
-
- if (sizeCallIndex == -1) return PatchResultError("Couldn't find call to size()")
-
- val sizeCallResultRegister =
- (arrayGenMethodImpl.instructions.elementAt(sizeCallIndex + 1) as OneRegisterInstruction).registerA
-
- arrayGenMethod.replaceInstruction(
- sizeCallIndex + 1,
- "const/4 v$sizeCallResultRegister, 0x0"
- )
-
- val (arrayLengthConstIndex, arrayLengthConst) = arrayGenMethodImpl.instructions.withIndex()
- .first { (it.value as? NarrowLiteralInstruction)?.narrowLiteral == 7 }
-
- val arrayLengthConstDestination = (arrayLengthConst as OneRegisterInstruction).registerA
-
- val videoSpeedsArrayType = "Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;->videoSpeeds:[F"
-
- arrayGenMethod.addInstructions(
- arrayLengthConstIndex + 1,
- """
- sget-object v$arrayLengthConstDestination, $videoSpeedsArrayType
- array-length v$arrayLengthConstDestination, v$arrayLengthConstDestination
- """
- )
-
- val (originalArrayFetchIndex, originalArrayFetch) = arrayGenMethodImpl.instructions.withIndex()
- .first {
- val reference = ((it.value as? ReferenceInstruction)?.reference as? FieldReference)
- reference?.definingClass?.contains("PlayerConfigModel") ?: false &&
- reference?.type == "[F"
- }
-
- val originalArrayFetchDestination = (originalArrayFetch as OneRegisterInstruction).registerA
-
- arrayGenMethod.replaceInstruction(
- originalArrayFetchIndex,
- "sget-object v$originalArrayFetchDestination, $videoSpeedsArrayType"
- )
-
- val limiterMethod = SpeedLimiterFingerprint.result?.mutableMethod!!
- val limiterMethodImpl = limiterMethod.implementation!!
-
- val (limiterMinConstIndex, limiterMinConst) = limiterMethodImpl.instructions.withIndex()
- .first { (it.value as? NarrowLiteralInstruction)?.narrowLiteral == 0.25f.toRawBits() }
- val (limiterMaxConstIndex, limiterMaxConst) = limiterMethodImpl.instructions.withIndex()
- .first { (it.value as? NarrowLiteralInstruction)?.narrowLiteral == 2.0f.toRawBits() }
-
- val limiterMinConstDestination = (limiterMinConst as OneRegisterInstruction).registerA
- val limiterMaxConstDestination = (limiterMaxConst as OneRegisterInstruction).registerA
-
- fun hexFloat(float: Float): String = "0x%08x".format(float.toRawBits())
-
- limiterMethod.replaceInstruction(
- limiterMinConstIndex,
- "const/high16 v$limiterMinConstDestination, ${hexFloat(speedLimitMin)}"
- )
- limiterMethod.replaceInstruction(
- limiterMaxConstIndex,
- "const/high16 v$limiterMaxConstDestination, ${hexFloat(speedLimitMax)}"
- )
-
- val constructorResult = VideoSpeedPatchFingerprint.result!!
- val constructor = constructorResult.mutableMethod
- val implementation = constructor.implementation!!
-
- val stepsGranularity = 8F
- val step = speedLimitMax
- .minus(speedLimitMin) // calculate the range of the speeds
- .div(speedsGranularity)
- .times(stepsGranularity)
- .roundToInt()
- .div(stepsGranularity)// round to nearest multiple of stepsGranularity
- .coerceAtLeast(1 / stepsGranularity) // ensure steps are at least 1/8th of the step granularity
-
- val videoSpeedsArray = buildList {
- DoubleStream
- .iterate(speedLimitMin.toDouble()) { it + step } // create a stream of speeds
- .let { speedStream ->
- for (speed in speedStream) {
- if (speed > speedLimitMax) break
- add(speed.toFloat().toRawBits())
- }
- }
- }
-
- // adjust the new array of speeds size
- constructor.replaceInstruction(
- 0,
- "const/16 v0, ${videoSpeedsArray.size}"
- )
-
- // create the payload with the new speeds
- val arrayPayloadIndex = implementation.instructions.size - 1
- implementation.replaceInstruction(
- arrayPayloadIndex,
- BuilderArrayPayload(
- 4,
- videoSpeedsArray
- )
- )
-
- return PatchResultSuccess()
- }
-
- companion object : OptionsContainer() {
- private fun String?.validate(max: Int? = null) = this?.toFloatOrNull() != null &&
- toFloat().let { float ->
- float > 0 && max?.let { max -> float <= max } ?: true
- }
-
- val videoSpeedsGranularity by option(
- PatchOption.StringOption(
- "granularity",
- "16",
- "Video speed granularity",
- "The granularity of the video speeds. The higher the value, the more speeds will be available.",
- true
- ) {
- it.validate()
- }
- )
-
- val minVideoSpeed by option(
- PatchOption.StringOption(
- "min",
- "0.25",
- "Minimum video speed",
- "The minimum video speed.",
- true
- ) {
- it.validate()
- }
- )
-
- val maxVideoSpeed by option(
- PatchOption.StringOption(
- "max",
- "5.0",
- "Maximum video speed",
- "The maximum video speed. Must be greater than the minimum video speed and smaller than 5.",
- true
- ) {
- it.validate(5)
- }
- )
- }
-}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/annotation/RememberPlaybackSpeedCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/annotation/RememberPlaybackSpeedCompatibility.kt
deleted file mode 100644
index 9fb318f77..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/annotation/RememberPlaybackSpeedCompatibility.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package app.revanced.patches.youtube.misc.video.speed.remember.annotation
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [Package("com.google.android.youtube", arrayOf("18.08.37", "18.15.40", "18.16.37"))]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class RememberPlaybackSpeedCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/annotation/VideoIdCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/annotation/VideoIdCompatibility.kt
deleted file mode 100644
index 63111f104..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/annotation/VideoIdCompatibility.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package app.revanced.patches.youtube.misc.video.videoid.annotation
-
-import app.revanced.patcher.annotation.Compatibility
-import app.revanced.patcher.annotation.Package
-
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
-@Target(AnnotationTarget.CLASS)
-internal annotation class VideoIdCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/annotations/CustomVideoBufferCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/annotations/CustomVideoBufferCompatibility.kt
index 37d47fee1..628499d60 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/annotations/CustomVideoBufferCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/annotations/CustomVideoBufferCompatibility.kt
@@ -4,22 +4,6 @@ import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
// TODO: delete this
-@Compatibility(
- [Package(
- "com.google.android.youtube", arrayOf(
- "17.49.37",
- "18.03.36",
- "18.03.42",
- "18.04.35",
- "18.04.41",
- "18.05.32",
- "18.05.35",
- "18.05.40",
- "18.08.37",
- "18.15.40",
- "18.16.37"
- )
- )]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class CustomVideoBufferCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/patch/ZoomHapticsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/patch/ZoomHapticsPatch.kt
index 89cccda3c..a3e5eedfe 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/patch/ZoomHapticsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/patch/ZoomHapticsPatch.kt
@@ -12,9 +12,9 @@ import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.smali.ExternalLabel
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
+import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.zoomhaptics.annotations.ZoomHapticsCompatibility
import app.revanced.patches.youtube.misc.zoomhaptics.fingerprints.ZoomHapticsFingerprint
@@ -32,7 +32,6 @@ class ZoomHapticsPatch : BytecodePatch(
SwitchPreference(
"revanced_disable_zoom_haptics",
StringResource("revanced_disable_zoom_haptics_title", "Disable zoom haptics"),
- true,
StringResource("revanced_disable_zoom_haptics_summary_on", "Haptics are disabled"),
StringResource("revanced_disable_zoom_haptics_summary_off", "Haptics are enabled")
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/annotations/HDRBrightnessCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/annotations/HDRBrightnessCompatibility.kt
new file mode 100644
index 000000000..29e7da076
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/annotations/HDRBrightnessCompatibility.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.youtube.video.hdrbrightness.annotations
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
+@Target(AnnotationTarget.CLASS)
+internal annotation class HDRBrightnessCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/fingerprints/HDRBrightnessFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/fingerprints/HDRBrightnessFingerprint.kt
similarity index 80%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/fingerprints/HDRBrightnessFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/fingerprints/HDRBrightnessFingerprint.kt
index 979f4e8a5..0db80f880 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/fingerprints/HDRBrightnessFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/fingerprints/HDRBrightnessFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.hdrbrightness.fingerprints
+package app.revanced.patches.youtube.video.hdrbrightness.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/patch/HDRBrightnessPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/patch/HDRBrightnessPatch.kt
similarity index 76%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/patch/HDRBrightnessPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/patch/HDRBrightnessPatch.kt
index f84efbee9..6b8ae5b01 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/patch/HDRBrightnessPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/patch/HDRBrightnessPatch.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.hdrbrightness.patch
+package app.revanced.patches.youtube.video.hdrbrightness.patch
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
@@ -10,8 +10,8 @@ import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.misc.hdrbrightness.annotations.HDRBrightnessCompatibility
-import app.revanced.patches.youtube.misc.hdrbrightness.fingerprints.HDRBrightnessFingerprint
+import app.revanced.patches.youtube.video.hdrbrightness.annotations.HDRBrightnessCompatibility
+import app.revanced.patches.youtube.video.hdrbrightness.fingerprints.HDRBrightnessFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource
@@ -30,13 +30,12 @@ class HDRBrightnessPatch : BytecodePatch(
listOf(HDRBrightnessFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
- SettingsPatch.PreferenceScreen.MISC.addPreferences(
+ SettingsPatch.PreferenceScreen.VIDEO.addPreferences(
SwitchPreference(
- "revanced_pref_hdr_autobrightness",
- StringResource("revanced_hdr_autobrightness_enabled_title", "Enable auto HDR brightness"),
- true,
- StringResource("revanced_hdr_autobrightness_summary_on", "Auto HDR brightness is enabled"),
- StringResource("revanced_hdr_autobrightness_summary_off", "Auto HDR brightness is disabled")
+ "revanced_hdr_auto_brightness",
+ StringResource("revanced_hdr_auto_brightness_title", "Enable auto HDR brightness"),
+ StringResource("revanced_hdr_auto_brightness_summary_on", "Auto HDR brightness is enabled"),
+ StringResource("revanced_hdr_auto_brightness_summary_off", "Auto HDR brightness is disabled")
)
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/annotation/VideoInformationCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/video/information/annotation/VideoInformationCompatibility.kt
similarity index 51%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/information/annotation/VideoInformationCompatibility.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/information/annotation/VideoInformationCompatibility.kt
index 6e7f87614..2ff6163df 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/annotation/VideoInformationCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/information/annotation/VideoInformationCompatibility.kt
@@ -1,10 +1,8 @@
-package app.revanced.patches.youtube.misc.video.information.annotation
+package app.revanced.patches.youtube.video.information.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package("com.google.android.youtube", arrayOf("18.08.37", "18.15.40", "18.16.37"))]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class VideoInformationCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/CreateVideoPlayerSeekbarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/CreateVideoPlayerSeekbarFingerprint.kt
similarity index 72%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/CreateVideoPlayerSeekbarFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/CreateVideoPlayerSeekbarFingerprint.kt
index 13f82a926..5bfa9579d 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/CreateVideoPlayerSeekbarFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/CreateVideoPlayerSeekbarFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.video.information.fingerprints
+package app.revanced.patches.youtube.video.information.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/OnPlaybackSpeedItemClickFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/OnPlaybackSpeedItemClickFingerprint.kt
similarity index 68%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/OnPlaybackSpeedItemClickFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/OnPlaybackSpeedItemClickFingerprint.kt
index 648f1a7e3..edb712070 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/OnPlaybackSpeedItemClickFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/OnPlaybackSpeedItemClickFingerprint.kt
@@ -1,10 +1,10 @@
-package app.revanced.patches.youtube.misc.video.information.fingerprints
+package app.revanced.patches.youtube.video.information.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode
object OnPlaybackSpeedItemClickFingerprint : MethodFingerprint(
- customFingerprint = { it.name == "onItemClick" },
+ customFingerprint = { methodDef, _ -> methodDef.name == "onItemClick" },
opcodes = listOf(
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/PlayerControllerSetTimeReferenceFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/PlayerControllerSetTimeReferenceFingerprint.kt
similarity index 81%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/PlayerControllerSetTimeReferenceFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/PlayerControllerSetTimeReferenceFingerprint.kt
index fe0355d68..628421a01 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/PlayerControllerSetTimeReferenceFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/PlayerControllerSetTimeReferenceFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.video.information.fingerprints
+package app.revanced.patches.youtube.video.information.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/PlayerInitFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/PlayerInitFingerprint.kt
similarity index 75%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/PlayerInitFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/PlayerInitFingerprint.kt
index 7e6485525..d772935b5 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/PlayerInitFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/PlayerInitFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.video.information.fingerprints
+package app.revanced.patches.youtube.video.information.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/SeekFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/SeekFingerprint.kt
similarity index 70%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/SeekFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/SeekFingerprint.kt
index 8f2ba9663..c6d9b2879 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/SeekFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/SeekFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.video.information.fingerprints
+package app.revanced.patches.youtube.video.information.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/VideoLengthFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/VideoLengthFingerprint.kt
similarity index 87%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/VideoLengthFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/VideoLengthFingerprint.kt
index 2d9e98682..89d4d16c6 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/VideoLengthFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/VideoLengthFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.video.information.fingerprints
+package app.revanced.patches.youtube.video.information.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/VideoTimeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/VideoTimeFingerprint.kt
similarity index 72%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/VideoTimeFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/VideoTimeFingerprint.kt
index d04b75377..c09c69ab9 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/VideoTimeFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/VideoTimeFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.video.information.fingerprints
+package app.revanced.patches.youtube.video.information.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/patch/VideoInformationPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/information/patch/VideoInformationPatch.kt
similarity index 85%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/information/patch/VideoInformationPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/information/patch/VideoInformationPatch.kt
index 77f44a9ed..1df612641 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/patch/VideoInformationPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/information/patch/VideoInformationPatch.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.video.information.patch
+package app.revanced.patches.youtube.video.information.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
@@ -19,16 +19,15 @@ import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.video.information.annotation.VideoInformationCompatibility
-import app.revanced.patches.youtube.misc.video.information.fingerprints.*
-import app.revanced.patches.youtube.misc.video.speed.remember.patch.RememberPlaybackSpeedPatch
-import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch
+import app.revanced.patches.youtube.video.information.annotation.VideoInformationCompatibility
+import app.revanced.patches.youtube.video.information.fingerprints.*
+import app.revanced.patches.youtube.video.speed.remember.patch.RememberPlaybackSpeedPatch
+import app.revanced.patches.youtube.video.videoid.patch.VideoIdPatch
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.BuilderInstruction
import org.jf.dexlib2.builder.MutableMethodImplementation
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
-import org.jf.dexlib2.iface.instruction.Instruction
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.immutable.ImmutableMethod
@@ -54,7 +53,7 @@ class VideoInformationPatch : BytecodePatch(
playerInitMethod = mutableClass.methods.first { MethodUtil.isConstructor(it) }
// hook the player controller for use through integrations
- onCreateHook(INTEGRATIONS_CLASS_DESCRIPTOR, "playerController_onCreateHook")
+ onCreateHook(INTEGRATIONS_CLASS_DESCRIPTOR, "initialize")
// seek method
val seekFingerprintResultMethod = SeekFingerprint.also { it.resolve(context, classDef) }.result!!.method
@@ -93,7 +92,7 @@ class VideoInformationPatch : BytecodePatch(
with(videoLengthMethodResult.mutableMethod) {
val videoLengthRegisterIndex = videoLengthMethodResult.scanResult.patternScanResult!!.endIndex - 2
- val videoLengthRegister = (instruction(videoLengthRegisterIndex) as OneRegisterInstruction).registerA
+ val videoLengthRegister = instruction(videoLengthRegisterIndex).registerA
val dummyRegisterForLong = videoLengthRegister + 1 // required for long values since they are wide
addInstruction(
@@ -140,7 +139,7 @@ class VideoInformationPatch : BytecodePatch(
speedSelectionInsertMethod = mutableMethod
speedSelectionInsertIndex = scanResult.patternScanResult!!.startIndex - 3
speedSelectionValueRegister =
- (mutableMethod.instruction(speedSelectionInsertIndex) as FiveRegisterInstruction).registerD
+ mutableMethod.instruction(speedSelectionInsertIndex).registerD
val speedSelectionMethodInstructions = mutableMethod.implementation!!.instructions
setPlaybackSpeedContainerClassFieldReference =
@@ -160,24 +159,32 @@ class VideoInformationPatch : BytecodePatch(
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/VideoInformation;"
private lateinit var playerInitMethod: MutableMethod
+ private var playerInitInsertIndex = 4
+
private lateinit var timeMethod: MutableMethod
+ private var timeInitInsertIndex = 2
+
private lateinit var highPrecisionTimeMethod: MutableMethod
+ private var highPrecisionInsertIndex = 0
- private fun MutableMethod.insert(insert: InsertIndex, register: String, descriptor: String) =
- addInstruction(insert.index, "invoke-static { $register }, $descriptor")
+ private fun MutableMethod.insert(insertIndex: Int, register: String, descriptor: String) =
+ addInstruction(insertIndex, "invoke-static { $register }, $descriptor")
- private fun MutableMethod.insertTimeHook(insert: InsertIndex, descriptor: String) =
- insert(insert, "p1, p2", descriptor)
+ private fun MutableMethod.insertTimeHook(insertIndex: Int, descriptor: String) =
+ insert(insertIndex, "p1, p2", descriptor)
/**
- * Hook the player controller.
+ * Hook the player controller. Called when a video is opened or the current video is changed.
+ *
+ * Note: This hook is called very early and is called before the video id, video time, video length,
+ * and many other data fields are set.
*
* @param targetMethodClass The descriptor for the class to invoke when the player controller is created.
* @param targetMethodName The name of the static method to invoke when the player controller is created.
*/
internal fun onCreateHook(targetMethodClass: String, targetMethodName: String) =
playerInitMethod.insert(
- InsertIndex.CREATE,
+ playerInitInsertIndex++,
"v0",
"$targetMethodClass->$targetMethodName(Ljava/lang/Object;)V"
)
@@ -191,7 +198,7 @@ class VideoInformationPatch : BytecodePatch(
*/
internal fun videoTimeHook(targetMethodClass: String, targetMethodName: String) =
timeMethod.insertTimeHook(
- InsertIndex.TIME,
+ timeInitInsertIndex++,
"$targetMethodClass->$targetMethodName(J)V"
)
@@ -205,20 +212,13 @@ class VideoInformationPatch : BytecodePatch(
*/
internal fun highPrecisionTimeHook(targetMethodClass: String, targetMethodName: String) =
highPrecisionTimeMethod.insertTimeHook(
- InsertIndex.HIGH_PRECISION_TIME,
+ highPrecisionInsertIndex++,
"$targetMethodClass->$targetMethodName(J)V"
)
- enum class InsertIndex(internal val index: Int) {
- CREATE(4),
- TIME(2),
- HIGH_PRECISION_TIME(0),
- }
-
private fun getReference(instructions: List, offset: Int, opcode: Opcode) =
- instructions[instructions.indexOfFirst { it.opcode == opcode } + offset].reference
-
- val Instruction.reference get() = (this as ReferenceInstruction).reference.toString()
+ (instructions[instructions.indexOfFirst { it.opcode == opcode } + offset] as ReferenceInstruction)
+ .reference.toString()
private lateinit var speedSelectionInsertMethod: MutableMethod
private var speedSelectionInsertIndex = 0
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/oldqualitylayout/annotations/OldQualityLayoutCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/video/oldqualitylayout/annotations/OldQualityLayoutCompatibility.kt
new file mode 100644
index 000000000..701f9974d
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/oldqualitylayout/annotations/OldQualityLayoutCompatibility.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.youtube.video.oldqualitylayout.annotations
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
+@Target(AnnotationTarget.CLASS)
+internal annotation class OldQualityLayoutCompatibility
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/oldqualitylayout/fingerprints/QualityMenuViewInflateFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/oldqualitylayout/fingerprints/QualityMenuViewInflateFingerprint.kt
new file mode 100644
index 000000000..bce667560
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/oldqualitylayout/fingerprints/QualityMenuViewInflateFingerprint.kt
@@ -0,0 +1,34 @@
+package app.revanced.patches.youtube.video.oldqualitylayout.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import app.revanced.patches.youtube.video.oldqualitylayout.patch.OldQualityLayoutResourcePatch
+import org.jf.dexlib2.Opcode
+import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
+
+object QualityMenuViewInflateFingerprint : MethodFingerprint(
+ opcodes = listOf(
+ Opcode.INVOKE_SUPER,
+ Opcode.CONST,
+ Opcode.CONST_4,
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.MOVE_RESULT_OBJECT,
+ Opcode.CONST,
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.MOVE_RESULT_OBJECT,
+ Opcode.CONST_16,
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.CONST,
+ Opcode.INVOKE_VIRTUAL,
+ Opcode.MOVE_RESULT_OBJECT,
+ Opcode.CHECK_CAST
+ ),
+ customFingerprint = { methodDef, _ ->
+ methodDef.implementation?.instructions?.any {
+ if (it.opcode != Opcode.CONST) return@any false
+
+ val literal = (it as WideLiteralInstruction).wideLiteral
+
+ literal == OldQualityLayoutResourcePatch.videoQualityBottomSheetListFragmentTitle
+ } ?: false
+ }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/patch/OldQualityLayoutPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/oldqualitylayout/patch/OldQualityLayoutPatch.kt
similarity index 55%
rename from src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/patch/OldQualityLayoutPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/oldqualitylayout/patch/OldQualityLayoutPatch.kt
index dd4597b01..1dcdf0303 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/patch/OldQualityLayoutPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/oldqualitylayout/patch/OldQualityLayoutPatch.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.layout.oldqualitylayout.patch
+package app.revanced.patches.youtube.video.oldqualitylayout.patch
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
@@ -10,36 +10,19 @@ import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patches.youtube.layout.oldqualitylayout.annotations.OldQualityLayoutCompatibility
-import app.revanced.patches.youtube.layout.oldqualitylayout.fingerprints.QualityMenuViewInflateFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-import app.revanced.patches.shared.settings.preference.impl.StringResource
-import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
+import app.revanced.patches.youtube.video.oldqualitylayout.annotations.OldQualityLayoutCompatibility
+import app.revanced.patches.youtube.video.oldqualitylayout.fingerprints.QualityMenuViewInflateFingerprint
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
+@DependsOn([IntegrationsPatch::class, OldQualityLayoutResourcePatch::class])
@Name("old-quality-layout")
-@Description("Enables the original video quality flyout in the video player settings")
+@Description("Enables the original video quality flyout in the video player settings.")
@OldQualityLayoutCompatibility
@Version("0.0.1")
-// new ReVanced users have no idea what it means to use the "old quality layout menu"
-// maybe rename this patch to better describe what it provides (ie: user-selectable-video-resolution )
-class OldQualityLayoutPatch : BytecodePatch(
- listOf(QualityMenuViewInflateFingerprint)
-) {
+class OldQualityLayoutPatch : BytecodePatch(listOf(QualityMenuViewInflateFingerprint)) {
override fun execute(context: BytecodeContext): PatchResult {
- SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
- SwitchPreference(
- "revanced_use_old_style_quality_settings",
- StringResource("revanced_old_style_quality_settings_enabled_title", "Use old video quality player menu"),
- true,
- StringResource("revanced_old_style_quality_settings_summary_on", "Old video quality menu is used"),
- StringResource("revanced_old_style_quality_settings_summary_off", "Old video quality menu is not used")
- )
- )
-
val inflateFingerprintResult = QualityMenuViewInflateFingerprint.result!!
val method = inflateFingerprintResult.mutableMethod
val instructions = method.implementation!!.instructions
@@ -58,4 +41,4 @@ class OldQualityLayoutPatch : BytecodePatch(
return PatchResultSuccess()
}
-}
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/oldqualitylayout/patch/OldQualityLayoutResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/oldqualitylayout/patch/OldQualityLayoutResourcePatch.kt
new file mode 100644
index 000000000..965486ce5
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/oldqualitylayout/patch/OldQualityLayoutResourcePatch.kt
@@ -0,0 +1,36 @@
+package app.revanced.patches.youtube.video.oldqualitylayout.patch
+
+import app.revanced.patcher.data.ResourceContext
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultError
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.ResourcePatch
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
+import app.revanced.patches.shared.settings.preference.impl.StringResource
+import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
+import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+
+@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
+class OldQualityLayoutResourcePatch : ResourcePatch {
+ override fun execute(context: ResourceContext): PatchResult {
+ SettingsPatch.PreferenceScreen.VIDEO.addPreferences(
+ SwitchPreference(
+ "revanced_show_old_video_menu",
+ StringResource("revanced_show_old_video_menu_title", "Use old video quality player menu"),
+ StringResource("revanced_show_old_video_menu_summary_on", "Old video quality menu is used"),
+ StringResource("revanced_show_old_video_menu_summary_off", "Old video quality menu is not used")
+ )
+ )
+
+ videoQualityBottomSheetListFragmentTitle =
+ ResourceMappingPatch.resourceMappings.find { it.name == "video_quality_bottom_sheet_list_fragment_title" }
+ ?.id ?: return PatchResultError("Could not find resource")
+
+ return PatchResultSuccess()
+ }
+
+ internal companion object {
+ var videoQualityBottomSheetListFragmentTitle = -1L
+ }
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/annotations/RememberVideoQualityCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/video/quality/annotations/RememberVideoQualityCompatibility.kt
similarity index 52%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/annotations/RememberVideoQualityCompatibility.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/quality/annotations/RememberVideoQualityCompatibility.kt
index 7e871ff60..789e422eb 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/annotations/RememberVideoQualityCompatibility.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/quality/annotations/RememberVideoQualityCompatibility.kt
@@ -1,10 +1,8 @@
-package app.revanced.patches.youtube.misc.video.quality.annotations
+package app.revanced.patches.youtube.video.quality.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
-@Compatibility(
- [Package("com.google.android.youtube", arrayOf("18.08.37", "18.15.40", "18.16.37"))]
-)
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
@Target(AnnotationTarget.CLASS)
internal annotation class RememberVideoQualityCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/SetQualityByIndexMethodClassFieldReferenceFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/SetQualityByIndexMethodClassFieldReferenceFingerprint.kt
similarity index 83%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/SetQualityByIndexMethodClassFieldReferenceFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/SetQualityByIndexMethodClassFieldReferenceFingerprint.kt
index 896b5de3e..d69bb8406 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/SetQualityByIndexMethodClassFieldReferenceFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/SetQualityByIndexMethodClassFieldReferenceFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.video.quality.fingerprints
+package app.revanced.patches.youtube.video.quality.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualityItemOnClickParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/VideoQualityItemOnClickParentFingerprint.kt
similarity index 76%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualityItemOnClickParentFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/VideoQualityItemOnClickParentFingerprint.kt
index 592c62fc0..a9e590671 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualityItemOnClickParentFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/VideoQualityItemOnClickParentFingerprint.kt
@@ -1,5 +1,5 @@
-package app.revanced.patches.youtube.misc.video.quality.fingerprints
+package app.revanced.patches.youtube.video.quality.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualitySetterFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/VideoQualitySetterFingerprint.kt
similarity index 88%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualitySetterFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/VideoQualitySetterFingerprint.kt
index 9a29d162b..ab95b0b5b 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualitySetterFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/VideoQualitySetterFingerprint.kt
@@ -1,5 +1,5 @@
-package app.revanced.patches.youtube.misc.video.quality.fingerprints
+package app.revanced.patches.youtube.video.quality.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/patch/RememberVideoQualityPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/quality/patch/RememberVideoQualityPatch.kt
similarity index 70%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/patch/RememberVideoQualityPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/quality/patch/RememberVideoQualityPatch.kt
index d5a03e33b..635563bf1 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/patch/RememberVideoQualityPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/quality/patch/RememberVideoQualityPatch.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.video.quality.patch
+package app.revanced.patches.youtube.video.quality.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
@@ -20,16 +20,16 @@ import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-import app.revanced.patches.youtube.misc.video.quality.annotations.RememberVideoQualityCompatibility
-import app.revanced.patches.youtube.misc.video.quality.fingerprints.SetQualityByIndexMethodClassFieldReferenceFingerprint
-import app.revanced.patches.youtube.misc.video.quality.fingerprints.VideoQualityItemOnClickParentFingerprint
-import app.revanced.patches.youtube.misc.video.quality.fingerprints.VideoQualitySetterFingerprint
-import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch
+import app.revanced.patches.youtube.video.information.patch.VideoInformationPatch
+import app.revanced.patches.youtube.video.quality.annotations.RememberVideoQualityCompatibility
+import app.revanced.patches.youtube.video.quality.fingerprints.SetQualityByIndexMethodClassFieldReferenceFingerprint
+import app.revanced.patches.youtube.video.quality.fingerprints.VideoQualityItemOnClickParentFingerprint
+import app.revanced.patches.youtube.video.quality.fingerprints.VideoQualitySetterFingerprint
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.reference.FieldReference
@Patch
-@DependsOn([IntegrationsPatch::class, VideoIdPatch::class, SettingsPatch::class])
+@DependsOn([IntegrationsPatch::class, VideoInformationPatch::class, SettingsPatch::class])
@Name("remember-video-quality")
@Description("Adds the ability to remember the video quality you chose in the video quality flyout.")
@RememberVideoQualityCompatibility
@@ -41,14 +41,38 @@ class RememberVideoQualityPatch : BytecodePatch(
)
) {
override fun execute(context: BytecodeContext): PatchResult {
- SettingsPatch.PreferenceScreen.MISC.addPreferences(
+ // This is bloated as each value has it's own String key/value
+ // ideally the entries would be raw values (and not a key to a String resource)
+ val entries = listOf(
+ StringResource("revanced_video_quality_default_entry_1", "Automatic quality"),
+ StringResource("revanced_video_quality_default_entry_2", "2160p"),
+ StringResource("revanced_video_quality_default_entry_3", "1440p"),
+ StringResource("revanced_video_quality_default_entry_4", "1080p"),
+ StringResource("revanced_video_quality_default_entry_5", "720p"),
+ StringResource("revanced_video_quality_default_entry_6", "480p"),
+ StringResource("revanced_video_quality_default_entry_7", "360p"),
+ StringResource("revanced_video_quality_default_entry_8", "280p"),
+ StringResource("revanced_video_quality_default_entry_9", "144p"),
+ )
+ val entryValues = listOf(
+ StringResource("revanced_video_quality_default_entry_value_1", "-2"),
+ StringResource("revanced_video_quality_default_entry_value_2", "2160"),
+ StringResource("revanced_video_quality_default_entry_value_3", "1440"),
+ StringResource("revanced_video_quality_default_entry_value_4", "1080"),
+ StringResource("revanced_video_quality_default_entry_value_5", "720"),
+ StringResource("revanced_video_quality_default_entry_value_6", "480"),
+ StringResource("revanced_video_quality_default_entry_value_7", "360"),
+ StringResource("revanced_video_quality_default_entry_value_8", "280"),
+ StringResource("revanced_video_quality_default_entry_value_9", "144"),
+ )
+
+ SettingsPatch.PreferenceScreen.VIDEO.addPreferences(
SwitchPreference(
"revanced_remember_video_quality_last_selected",
StringResource(
"revanced_remember_video_quality_last_selected_title",
"Remember video quality changes"
),
- true,
StringResource(
"revanced_remember_video_quality_last_selected_summary_on",
"Quality changes apply to all videos"
@@ -57,52 +81,25 @@ class RememberVideoQualityPatch : BytecodePatch(
"revanced_remember_video_quality_last_selected_summary_off",
"Quality changes only apply to the current video"
)
- )
- )
-
- // This is bloated as each value has it's own String key/value
- // ideally the entries would be raw values (and not a key to a String resource)
- val entries = listOf(
- StringResource("revanced_default_quality_entry_1", "Automatic quality"),
- StringResource("revanced_default_quality_entry_2", "2160p"),
- StringResource("revanced_default_quality_entry_3", "1440p"),
- StringResource("revanced_default_quality_entry_4", "1080p"),
- StringResource("revanced_default_quality_entry_5", "720p"),
- StringResource("revanced_default_quality_entry_6", "480p"),
- StringResource("revanced_default_quality_entry_7", "360p"),
- StringResource("revanced_default_quality_entry_8", "280p"),
- StringResource("revanced_default_quality_entry_9", "144p"),
- )
- val entryValues = listOf(
- StringResource("revanced_default_quality_entry_value_1", "-2"),
- StringResource("revanced_default_quality_entry_value_2", "2160"),
- StringResource("revanced_default_quality_entry_value_3", "1440"),
- StringResource("revanced_default_quality_entry_value_4", "1080"),
- StringResource("revanced_default_quality_entry_value_5", "720"),
- StringResource("revanced_default_quality_entry_value_6", "480"),
- StringResource("revanced_default_quality_entry_value_7", "360"),
- StringResource("revanced_default_quality_entry_value_8", "280"),
- StringResource("revanced_default_quality_entry_value_9", "144"),
- )
- SettingsPatch.PreferenceScreen.MISC.addPreferences(
+ ),
ListPreference(
- "revanced_default_video_quality_wifi",
+ "revanced_video_quality_default_wifi",
StringResource(
- "revanced_default_video_quality_wifi_title",
+ "revanced_video_quality_default_wifi_title",
"Default video quality on Wi-Fi network"
),
- ArrayResource("revanced_video_quality_wifi_entry", entries),
- ArrayResource("revanced_video_quality_wifi_entry_values", entryValues)
+ ArrayResource("revanced_video_quality_default_wifi_entry", entries),
+ ArrayResource("revanced_video_quality_default_wifi_entry_values", entryValues)
// default value and summary are set by integrations after loading
),
ListPreference(
- "revanced_default_video_quality_mobile",
+ "revanced_video_quality_default_mobile",
StringResource(
- "revanced_default_video_quality_mobile_title",
+ "revanced_video_quality_default_mobile_title",
"Default video quality on mobile network"
),
- ArrayResource("revanced_video_quality_mobile_entries", entries),
- ArrayResource("revanced_video_quality_mobile_entry_values", entryValues)
+ ArrayResource("revanced_video_quality_default_mobile_entries", entries),
+ ArrayResource("revanced_video_quality_default_mobile_values", entryValues)
)
)
@@ -114,7 +111,7 @@ class RememberVideoQualityPatch : BytecodePatch(
* Conveniently, at this point the video quality is overridden to the remembered playback speed.
*/
- VideoIdPatch.injectCall("$INTEGRATIONS_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;)V")
+ VideoInformationPatch.onCreateHook(INTEGRATIONS_CLASS_DESCRIPTOR, "newVideoStarted")
// Inject a call to set the remembered quality once a video loads.
VideoQualitySetterFingerprint.result?.also {
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/speed/VideoSpeed.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/VideoSpeed.kt
new file mode 100644
index 000000000..a079bd0f3
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/speed/VideoSpeed.kt
@@ -0,0 +1,27 @@
+package app.revanced.patches.youtube.video.speed
+
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patches.youtube.video.speed.custom.patch.CustomVideoSpeedPatch
+import app.revanced.patches.youtube.video.speed.remember.patch.RememberPlaybackSpeedPatch
+
+@Patch
+@Name("video-speed")
+@Description("Adds custom video speeds and ability to remember the playback speed you chose in the video playback speed flyout.")
+@DependsOn([CustomVideoSpeedPatch::class, RememberPlaybackSpeedPatch::class])
+@VideoSpeedCompatibility
+@Version("0.0.1")
+class VideoSpeed : BytecodePatch() {
+
+ override fun execute(context: BytecodeContext): PatchResult {
+ return PatchResultSuccess() // All patches this patch depends on succeed.
+ }
+
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/speed/VideoSpeedCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/VideoSpeedCompatibility.kt
new file mode 100644
index 000000000..b97e92931
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/speed/VideoSpeedCompatibility.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.youtube.video.speed
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
+@Target(AnnotationTarget.CLASS)
+internal annotation class VideoSpeedCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/SpeedArrayGeneratorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/fingerprints/SpeedArrayGeneratorFingerprint.kt
similarity index 89%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/SpeedArrayGeneratorFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/fingerprints/SpeedArrayGeneratorFingerprint.kt
index e4e336880..4d624dab2 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/SpeedArrayGeneratorFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/fingerprints/SpeedArrayGeneratorFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.video.speed.custom.fingerprints
+package app.revanced.patches.youtube.video.speed.custom.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/SpeedLimiterFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/fingerprints/SpeedLimiterFingerprint.kt
similarity index 87%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/SpeedLimiterFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/fingerprints/SpeedLimiterFingerprint.kt
index 4cb98cd4d..30c315de8 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/SpeedLimiterFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/fingerprints/SpeedLimiterFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.video.speed.custom.fingerprints
+package app.revanced.patches.youtube.video.speed.custom.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/fingerprints/VideoSpeedPatchFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/fingerprints/VideoSpeedPatchFingerprint.kt
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/patch/CustomVideoSpeedPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/patch/CustomVideoSpeedPatch.kt
new file mode 100644
index 000000000..ae5e53d83
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/patch/CustomVideoSpeedPatch.kt
@@ -0,0 +1,121 @@
+package app.revanced.patches.youtube.video.speed.custom.patch
+
+import app.revanced.patcher.annotation.Description
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.annotation.Version
+import app.revanced.patcher.data.BytecodeContext
+import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.extensions.replaceInstruction
+import app.revanced.patcher.patch.*
+import app.revanced.patcher.patch.annotations.DependsOn
+import app.revanced.patches.shared.settings.preference.impl.InputType
+import app.revanced.patches.shared.settings.preference.impl.StringResource
+import app.revanced.patches.shared.settings.preference.impl.TextPreference
+import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
+import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
+import app.revanced.patches.youtube.video.speed.custom.fingerprints.SpeedArrayGeneratorFingerprint
+import app.revanced.patches.youtube.video.speed.custom.fingerprints.SpeedLimiterFingerprint
+import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
+import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
+import org.jf.dexlib2.iface.instruction.ReferenceInstruction
+import org.jf.dexlib2.iface.reference.FieldReference
+import org.jf.dexlib2.iface.reference.MethodReference
+
+@Name("custom-video-speed")
+@Description("Adds custom video speed options.")
+@DependsOn([IntegrationsPatch::class])
+@Version("0.0.1")
+class CustomVideoSpeedPatch : BytecodePatch(
+ listOf(
+ SpeedArrayGeneratorFingerprint, SpeedLimiterFingerprint
+ )
+) {
+
+ override fun execute(context: BytecodeContext): PatchResult {
+ SettingsPatch.PreferenceScreen.VIDEO.addPreferences(
+ TextPreference(
+ key = "revanced_custom_playback_speeds",
+ title = StringResource(
+ "revanced_custom_playback_speeds_title",
+ "Custom playback speeds"
+ ),
+ inputType = InputType.TEXT_MULTI_LINE,
+ summary = StringResource(
+ "revanced_custom_playback_speeds_summary",
+ "Add or change the video speeds available"
+ )
+ )
+ )
+
+ val arrayGenMethod = SpeedArrayGeneratorFingerprint.result?.mutableMethod!!
+ val arrayGenMethodImpl = arrayGenMethod.implementation!!
+
+ val sizeCallIndex = arrayGenMethodImpl.instructions
+ .indexOfFirst { ((it as? ReferenceInstruction)?.reference as? MethodReference)?.name == "size" }
+
+ if (sizeCallIndex == -1) return PatchResultError("Couldn't find call to size()")
+
+ val sizeCallResultRegister =
+ (arrayGenMethodImpl.instructions.elementAt(sizeCallIndex + 1) as OneRegisterInstruction).registerA
+
+ arrayGenMethod.replaceInstruction(
+ sizeCallIndex + 1,
+ "const/4 v$sizeCallResultRegister, 0x0"
+ )
+
+ val (arrayLengthConstIndex, arrayLengthConst) = arrayGenMethodImpl.instructions.withIndex()
+ .first { (it.value as? NarrowLiteralInstruction)?.narrowLiteral == 7 }
+
+ val arrayLengthConstDestination = (arrayLengthConst as OneRegisterInstruction).registerA
+
+ val videoSpeedsArrayType = "Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;->customVideoSpeeds:[F"
+
+ arrayGenMethod.addInstructions(
+ arrayLengthConstIndex + 1,
+ """
+ sget-object v$arrayLengthConstDestination, $videoSpeedsArrayType
+ array-length v$arrayLengthConstDestination, v$arrayLengthConstDestination
+ """
+ )
+
+ val (originalArrayFetchIndex, originalArrayFetch) = arrayGenMethodImpl.instructions.withIndex()
+ .first {
+ val reference = ((it.value as? ReferenceInstruction)?.reference as? FieldReference)
+ reference?.definingClass?.contains("PlayerConfigModel") ?: false &&
+ reference?.type == "[F"
+ }
+
+ val originalArrayFetchDestination = (originalArrayFetch as OneRegisterInstruction).registerA
+
+ arrayGenMethod.replaceInstruction(
+ originalArrayFetchIndex,
+ "sget-object v$originalArrayFetchDestination, $videoSpeedsArrayType"
+ )
+
+ val limiterMethod = SpeedLimiterFingerprint.result?.mutableMethod!!
+ val limiterMethodImpl = limiterMethod.implementation!!
+
+ val lowerLimitConst = 0.25f.toRawBits()
+ val upperLimitConst = 2.0f.toRawBits()
+ val (limiterMinConstIndex, limiterMinConst) = limiterMethodImpl.instructions.withIndex()
+ .first { (it.value as? NarrowLiteralInstruction)?.narrowLiteral == lowerLimitConst }
+ val (limiterMaxConstIndex, limiterMaxConst) = limiterMethodImpl.instructions.withIndex()
+ .first { (it.value as? NarrowLiteralInstruction)?.narrowLiteral == upperLimitConst }
+
+ val limiterMinConstDestination = (limiterMinConst as OneRegisterInstruction).registerA
+ val limiterMaxConstDestination = (limiterMaxConst as OneRegisterInstruction).registerA
+
+ // edit: alternatively this might work by overriding with fixed values such as 0.1x and 10x
+ limiterMethod.replaceInstruction(
+ limiterMinConstIndex,
+ "sget v$limiterMinConstDestination, Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;->minVideoSpeed:F"
+ )
+ limiterMethod.replaceInstruction(
+ limiterMaxConstIndex,
+ "sget v$limiterMaxConstDestination, Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;->maxVideoSpeed:F"
+ )
+
+ return PatchResultSuccess()
+ }
+
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/fingerprint/InitializePlaybackSpeedValuesFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/fingerprint/InitializePlaybackSpeedValuesFingerprint.kt
similarity index 75%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/fingerprint/InitializePlaybackSpeedValuesFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/fingerprint/InitializePlaybackSpeedValuesFingerprint.kt
index e244a298e..31ac21e8a 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/fingerprint/InitializePlaybackSpeedValuesFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/fingerprint/InitializePlaybackSpeedValuesFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.video.speed.remember.fingerprint
+package app.revanced.patches.youtube.video.speed.remember.fingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/patch/RememberPlaybackSpeedPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/patch/RememberPlaybackSpeedPatch.kt
similarity index 74%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/patch/RememberPlaybackSpeedPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/patch/RememberPlaybackSpeedPatch.kt
index 4895e665a..625d773df 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/patch/RememberPlaybackSpeedPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/patch/RememberPlaybackSpeedPatch.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.video.speed.remember.patch
+package app.revanced.patches.youtube.video.speed.remember.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
@@ -7,9 +7,10 @@ import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
-import app.revanced.patcher.patch.*
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
-import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.settings.preference.impl.ArrayResource
import app.revanced.patches.shared.settings.preference.impl.ListPreference
@@ -17,17 +18,14 @@ import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-import app.revanced.patches.youtube.misc.video.information.patch.VideoInformationPatch
-import app.revanced.patches.youtube.misc.video.information.patch.VideoInformationPatch.Companion.reference
-import app.revanced.patches.youtube.misc.video.speed.remember.annotation.RememberPlaybackSpeedCompatibility
-import app.revanced.patches.youtube.misc.video.speed.remember.fingerprint.InitializePlaybackSpeedValuesFingerprint
-import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch
+import app.revanced.patches.youtube.video.information.patch.VideoInformationPatch
+import app.revanced.patches.youtube.video.speed.custom.patch.CustomVideoSpeedPatch
+import app.revanced.patches.youtube.video.speed.remember.fingerprint.InitializePlaybackSpeedValuesFingerprint
+import org.jf.dexlib2.iface.instruction.ReferenceInstruction
-@Patch
@Name("remember-playback-speed")
@Description("Adds the ability to remember the playback speed you chose in the video playback speed flyout.")
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class, VideoIdPatch::class, VideoInformationPatch::class])
-@RememberPlaybackSpeedCompatibility
+@DependsOn([IntegrationsPatch::class, SettingsPatch::class, VideoInformationPatch::class, CustomVideoSpeedPatch::class])
@Version("0.0.1")
class RememberPlaybackSpeedPatch : BytecodePatch(
listOf(
@@ -35,14 +33,13 @@ class RememberPlaybackSpeedPatch : BytecodePatch(
)
) {
override fun execute(context: BytecodeContext): PatchResult {
- SettingsPatch.PreferenceScreen.MISC.addPreferences(
+ SettingsPatch.PreferenceScreen.VIDEO.addPreferences(
SwitchPreference(
"revanced_remember_playback_speed_last_selected",
StringResource(
"revanced_remember_playback_speed_last_selected_title",
"Remember playback speed changes"
),
- true,
StringResource(
"revanced_remember_playback_speed_last_selected_summary_on",
"Playback speed changes apply to all videos"
@@ -51,32 +48,28 @@ class RememberPlaybackSpeedPatch : BytecodePatch(
"revanced_remember_playback_speed_last_selected_summary_off",
"Playback speed changes only apply to the current video"
)
- )
- )
-
- SettingsPatch.PreferenceScreen.MISC.addPreferences(
+ ),
ListPreference(
- "revanced_default_playback_speed",
+ "revanced_playback_speed_default",
StringResource(
- "revanced_default_playback_speed_title",
+ "revanced_playback_speed_default_title",
"Default playback speed"
),
// Dummy data:
// Entries and values are set by Integrations code based on the actual speeds available,
// and the values set here are ignored and do nothing.
ArrayResource(
- "revanced_default_playback_speed_entries",
- listOf(StringResource("revanced_default_playback_speed_entry", "1.0x"))
+ "revanced_playback_speed_default_entries",
+ listOf(StringResource("revanced_playback_speed_default_entries", "1.0x"))
),
ArrayResource(
- "revanced_default_playback_speed_entry_values",
- listOf(StringResource("revanced_default_playback_speed_entry_value", "1.0"))
+ "revanced_playback_speed_default_entry_values",
+ listOf(StringResource("revanced_playback_speed_default_entry_value", "1.0"))
)
)
)
- VideoIdPatch.injectCall("${INTEGRATIONS_CLASS_DESCRIPTOR}->newVideoLoaded(Ljava/lang/String;)V")
-
+ VideoInformationPatch.onCreateHook(INTEGRATIONS_CLASS_DESCRIPTOR, "newVideoStarted")
VideoInformationPatch.userSelectedPlaybackSpeedHook(
INTEGRATIONS_CLASS_DESCRIPTOR, "userSelectedPlaybackSpeed")
@@ -85,7 +78,8 @@ class RememberPlaybackSpeedPatch : BytecodePatch(
*/
InitializePlaybackSpeedValuesFingerprint.result?.apply {
// Infer everything necessary for calling the method setPlaybackSpeed().
- val onItemClickListenerClassFieldReference = mutableMethod.instruction(0).reference
+ val onItemClickListenerClassFieldReference =
+ mutableMethod.instruction(0).reference
// Registers are not used at index 0, so they can be freely used.
mutableMethod.addInstructions(
@@ -122,4 +116,4 @@ class RememberPlaybackSpeedPatch : BytecodePatch(
const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/playback/speed/RememberPlaybackSpeedPatch;"
}
-}
\ No newline at end of file
+}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/videoid/annotation/VideoIdCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/annotation/VideoIdCompatibility.kt
new file mode 100644
index 000000000..660f7d8ad
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/annotation/VideoIdCompatibility.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.youtube.video.videoid.annotation
+
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Package
+
+@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
+@Target(AnnotationTarget.CLASS)
+internal annotation class VideoIdCompatibility
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/fingerprint/VideoIdFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/fingerprint/VideoIdFingerprint.kt
similarity index 77%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/fingerprint/VideoIdFingerprint.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/videoid/fingerprint/VideoIdFingerprint.kt
index bed9e90d3..d9c51ab7c 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/fingerprint/VideoIdFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/fingerprint/VideoIdFingerprint.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.video.videoid.fingerprint
+package app.revanced.patches.youtube.video.videoid.fingerprint
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
@@ -9,7 +9,7 @@ import org.jf.dexlib2.Opcode
@FuzzyPatternScanMethod(2)
object VideoIdFingerprint : MethodFingerprint(
returnType = "V",
- access = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("L"),
opcodes = listOf(
Opcode.IF_EQZ,
@@ -26,6 +26,7 @@ object VideoIdFingerprint : MethodFingerprint(
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT
),
- null,
- { it.definingClass.endsWith("SubtitlesOverlayPresenter;") }
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass.endsWith("SubtitlesOverlayPresenter;")
+ }
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/fingerprint/VideoIdFingerprintBackgroundPlay.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/fingerprint/VideoIdFingerprintBackgroundPlay.kt
similarity index 56%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/fingerprint/VideoIdFingerprintBackgroundPlay.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/videoid/fingerprint/VideoIdFingerprintBackgroundPlay.kt
index 44c14a2c2..6f7da47b4 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/fingerprint/VideoIdFingerprintBackgroundPlay.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/fingerprint/VideoIdFingerprintBackgroundPlay.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.video.videoid.fingerprint
+package app.revanced.patches.youtube.video.videoid.fingerprint
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
@@ -7,10 +7,10 @@ import org.jf.dexlib2.Opcode
object VideoIdFingerprintBackgroundPlay : MethodFingerprint(
returnType = "V",
- access = AccessFlags.DECLARED_SYNCHRONIZED or AccessFlags.FINAL or AccessFlags.PUBLIC,
+ accessFlags = AccessFlags.DECLARED_SYNCHRONIZED or AccessFlags.FINAL or AccessFlags.PUBLIC,
parameters = listOf("L"),
opcodes = listOf(Opcode.INVOKE_INTERFACE),
- customFingerprint = {
- it.definingClass.endsWith("PlaybackLifecycleMonitor;")
+ customFingerprint = { methodDef, _ ->
+ methodDef.definingClass.endsWith("PlaybackLifecycleMonitor;")
}
)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/patch/VideoIdPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/patch/VideoIdPatch.kt
similarity index 87%
rename from src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/patch/VideoIdPatch.kt
rename to src/main/kotlin/app/revanced/patches/youtube/video/videoid/patch/VideoIdPatch.kt
index bf961de7b..4b8fbcc47 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/patch/VideoIdPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/videoid/patch/VideoIdPatch.kt
@@ -1,4 +1,4 @@
-package app.revanced.patches.youtube.misc.video.videoid.patch
+package app.revanced.patches.youtube.video.videoid.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
@@ -13,9 +13,9 @@ import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.video.videoid.annotation.VideoIdCompatibility
-import app.revanced.patches.youtube.misc.video.videoid.fingerprint.VideoIdFingerprint
-import app.revanced.patches.youtube.misc.video.videoid.fingerprint.VideoIdFingerprintBackgroundPlay
+import app.revanced.patches.youtube.video.videoid.annotation.VideoIdCompatibility
+import app.revanced.patches.youtube.video.videoid.fingerprint.VideoIdFingerprint
+import app.revanced.patches.youtube.video.videoid.fingerprint.VideoIdFingerprintBackgroundPlay
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@Name("video-id-hook")
@@ -33,7 +33,7 @@ class VideoIdPatch : BytecodePatch(
result.mutableMethod.also {
insertMethod = it
}.apply {
- videoIdRegister = (instruction(videoIdRegisterInstructionIndex) as OneRegisterInstruction).registerA
+ videoIdRegister = instruction(videoIdRegisterInstructionIndex).registerA
insertIndex = videoIdRegisterInstructionIndex + 1
}
} ?: return VideoIdFingerprint.toErrorResult()
@@ -44,7 +44,7 @@ class VideoIdPatch : BytecodePatch(
result.mutableMethod.also {
backgroundPlaybackMethod = it
}.apply {
- backgroundPlaybackVideoIdRegister = (instruction(endIndex + 1) as OneRegisterInstruction).registerA
+ backgroundPlaybackVideoIdRegister = instruction(endIndex + 1).registerA
backgroundPlaybackInsertIndex = endIndex + 2
}
} ?: return VideoIdFingerprintBackgroundPlay.toErrorResult()
diff --git a/src/main/kotlin/app/revanced/patches/youtubevanced/ad/general/fingerprints/ContainsAdFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtubevanced/ad/general/fingerprints/ContainsAdFingerprint.kt
index ed26fa039..0b0c1a9b5 100644
--- a/src/main/kotlin/app/revanced/patches/youtubevanced/ad/general/fingerprints/ContainsAdFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/youtubevanced/ad/general/fingerprints/ContainsAdFingerprint.kt
@@ -8,7 +8,7 @@ import org.jf.dexlib2.Opcode
object ContainsAdFingerprint:MethodFingerprint(
returnType = "Z",
parameters = listOf("L", "L"),
- access = AccessFlags.STATIC or AccessFlags.PUBLIC,
+ accessFlags = AccessFlags.STATIC or AccessFlags.PUBLIC,
opcodes = listOf(
Opcode.CONST_STRING,
Opcode.INVOKE_INTERFACE,
@@ -18,7 +18,7 @@ object ContainsAdFingerprint:MethodFingerprint(
Opcode.INVOKE_INTERFACE
),
strings = listOf("ads_video_with_context"),
- customFingerprint = { methodDef ->
+ customFingerprint = { methodDef, _ ->
methodDef.name == "containsAd" && methodDef.definingClass.endsWith("LithoAdRemoval;")
}
) {
diff --git a/src/main/kotlin/app/revanced/patches/youtubevanced/ad/general/patch/HideAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtubevanced/ad/general/patch/HideAdsPatch.kt
index 09fd98117..e704e983d 100644
--- a/src/main/kotlin/app/revanced/patches/youtubevanced/ad/general/patch/HideAdsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtubevanced/ad/general/patch/HideAdsPatch.kt
@@ -32,7 +32,7 @@ class HideAdsPatch : BytecodePatch(
ContainsAdFingerprint.result?.let { result ->
result.mutableMethod.apply {
val insertIndex = result.scanResult.patternScanResult!!.endIndex + 1
- val adsListRegister = (instruction(insertIndex - 2) as Instruction21c).registerA
+ val adsListRegister = instruction(insertIndex - 2).registerA
listOf(
"_buttoned_layout",
diff --git a/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/fingerprints/IsPremiumFingerprint.kt b/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/fingerprints/IsPremiumFingerprint.kt
index 0a7f01a25..4835c4048 100644
--- a/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/fingerprints/IsPremiumFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/fingerprints/IsPremiumFingerprint.kt
@@ -7,7 +7,7 @@ import org.jf.dexlib2.Opcode
object IsPremiumFingerprint : MethodFingerprint(
returnType = "Z",
- access = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
opcodes = listOf(
Opcode.IGET_BOOLEAN,
Opcode.RETURN,
diff --git a/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/fingerprints/YukaUserConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/fingerprints/YukaUserConstructorFingerprint.kt
index 85351e471..67aba3720 100644
--- a/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/fingerprints/YukaUserConstructorFingerprint.kt
+++ b/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/fingerprints/YukaUserConstructorFingerprint.kt
@@ -6,7 +6,7 @@ import org.jf.dexlib2.AccessFlags
object YukaUserConstructorFingerprint : MethodFingerprint(
returnType = "V",
- access = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
strings = listOf(
"premiumProvider"
)
diff --git a/src/main/kotlin/app/revanced/util/patch/BytecodeUtils.kt b/src/main/kotlin/app/revanced/util/patch/BytecodeUtils.kt
new file mode 100644
index 000000000..d62857323
--- /dev/null
+++ b/src/main/kotlin/app/revanced/util/patch/BytecodeUtils.kt
@@ -0,0 +1,16 @@
+package app.revanced.util.patch
+
+import org.jf.dexlib2.Opcode
+import org.jf.dexlib2.iface.Method
+import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
+
+/**
+ * @return the first constant instruction with the resource id, or -1 if not found.
+ */
+fun Method.indexOfFirstConstantInstruction(constantValue: Long): Int {
+ return implementation?.let {
+ it.instructions.indexOfFirst { instruction ->
+ instruction.opcode == Opcode.CONST && (instruction as WideLiteralInstruction).wideLiteral == constantValue
+ }
+ } ?: -1
+}
\ No newline at end of file
diff --git a/src/main/resources/copyvideourl/host/values/strings.xml b/src/main/resources/copyvideourl/host/values/strings.xml
new file mode 100644
index 000000000..8452816c3
--- /dev/null
+++ b/src/main/resources/copyvideourl/host/values/strings.xml
@@ -0,0 +1,5 @@
+
+
+ URL copied to clipboard
+ URL with timestamp copied
+
diff --git a/src/main/resources/returnyoutubedislike/host/values/strings.xml b/src/main/resources/returnyoutubedislike/host/values/strings.xml
index 31ca93597..e887fe5ce 100644
--- a/src/main/resources/returnyoutubedislike/host/values/strings.xml
+++ b/src/main/resources/returnyoutubedislike/host/values/strings.xml
@@ -13,6 +13,10 @@
Dislikes are shown
Dislikes are not shown
+ Show dislikes on Shorts
+ Dislikes shown on Shorts
+ Dislikes hidden on Shorts
+
Dislikes as percentage
Dislikes shown as percentage
Dislikes shown as number
@@ -21,9 +25,13 @@
Like button styled for minimum width
Like button styled for best appearance
+ Show toast if API not available
+ Toast shown if ReturnYouTubeDislike API is not available
+ Toast not shown if ReturnYouTubeDislike API is not available
+
About
ReturnYouTubeDislike.com
- Dislike data is provided by the Return YouTube Dislike API. Tap here to learn more.
+ Data is provided by the Return YouTube Dislike API. Tap here to learn more.
ReturnYouTubeDislike API statistics of this device
diff --git a/src/main/resources/settings/drawable-ldrtl-xxxhdpi/quantum_ic_arrow_back_white_24.png b/src/main/resources/settings/drawable-ldrtl-xxxhdpi/quantum_ic_arrow_back_white_24.png
deleted file mode 100644
index d409b544b..000000000
Binary files a/src/main/resources/settings/drawable-ldrtl-xxxhdpi/quantum_ic_arrow_back_white_24.png and /dev/null differ
diff --git a/src/main/resources/settings/drawable-xxxhdpi/quantum_ic_arrow_back_white_24.png b/src/main/resources/settings/drawable-xxxhdpi/quantum_ic_arrow_back_white_24.png
deleted file mode 100644
index e27034d67..000000000
Binary files a/src/main/resources/settings/drawable-xxxhdpi/quantum_ic_arrow_back_white_24.png and /dev/null differ
diff --git a/src/main/resources/settings/host/values/strings.xml b/src/main/resources/settings/host/values/strings.xml
index c0740672f..75802473c 100644
--- a/src/main/resources/settings/host/values/strings.xml
+++ b/src/main/resources/settings/host/values/strings.xml
@@ -1,4 +1,12 @@
+ ReVanced
Do you wish to proceed?
+ Reset
+
+ Import
+ Copy
+ ReVanced settings reset to default
+ Imported %d settings
+ Import failed: %s
diff --git a/src/main/resources/settings/layout/revanced_settings_toolbar.xml b/src/main/resources/settings/layout/revanced_settings_toolbar.xml
deleted file mode 100644
index 86c717712..000000000
--- a/src/main/resources/settings/layout/revanced_settings_toolbar.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/main/resources/settings/layout/revanced_settings_with_toolbar.xml b/src/main/resources/settings/layout/revanced_settings_with_toolbar.xml
index 21ff59780..150088114 100644
--- a/src/main/resources/settings/layout/revanced_settings_with_toolbar.xml
+++ b/src/main/resources/settings/layout/revanced_settings_with_toolbar.xml
@@ -1,4 +1,33 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/settings/layout/revanced_settings_with_toolbar_layout.xml b/src/main/resources/settings/layout/revanced_settings_with_toolbar_layout.xml
deleted file mode 100644
index 31b20d945..000000000
--- a/src/main/resources/settings/layout/revanced_settings_with_toolbar_layout.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/src/main/resources/sponsorblock/host/values/strings.xml b/src/main/resources/sponsorblock/host/values/strings.xml
index c8f014afc..d451ce290 100644
--- a/src/main/resources/sponsorblock/host/values/strings.xml
+++ b/src/main/resources/sponsorblock/host/values/strings.xml
@@ -35,6 +35,9 @@
Show me
General
+ Show toast if API is not available
+ Toast shown if SponsorBlock API is not available
+ Toast not shown if SponsorBlock API is not available
Enable skip count tracking
Lets the SponsorBlock leaderboard know how much time is saved. A message is sent to the leaderboard each time a segment is skipped
Skip count tracking is not enabled
@@ -42,17 +45,21 @@
Segments shorter than this value (in seconds) will not be shown or skipped
Your private user id
This should be kept private. This is like a password and should not be shared with anyone. If someone has this, they can impersonate you
- User id cannot be blank
+ Private user id must be at least 30 characters long
Change API URL
The address SponsorBlock uses to make calls to the server. Do not change this unless you know what you\'re doing
API URL reset
API URL is invalid
API URL changed
Import/Export settings
+ Copy
Your SponsorBlock JSON configuration that can be imported/exported to ReVanced and other SponsorBlock platforms. This includes your private user id. Be sure to share this wisely
Settings imported successfully
Failed to import: %s
- Failed to export settings (try clearing app data)
+ Failed to export: %s
+
+ Your settings contain a private SponsorBlock user id.\n\nYour user id is like a password and it should never be shared.\n
+ Do not show again
Change segment behavior
Sponsor
@@ -113,10 +120,10 @@
Show in seek bar
Disable
- Can\'t submit the segment: %s
- Unable to submit segments (API timed out)
- Unable to submit segments (status: %d %s)
- Can\'t submit the segment.\nRate Limited (too many from the same user or IP)
+ Unable to submit segment: %s
+ SponsorBlock is temporarily down
+ Unable to submit segment (status: %d %s)
+ Unable to submit segment.\nRate Limited (too many from the same user or IP)
Can\'t submit the segment: %s
Can\'t submit the segment.\nAlready exists
Segment submitted successfully
diff --git a/src/main/resources/theme/values-night-v31/styles.xml b/src/main/resources/theme/values-night-v31/styles.xml
deleted file mode 100644
index 53da895f8..000000000
--- a/src/main/resources/theme/values-night-v31/styles.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-