diff --git a/.github/ISSUE_TEMPLATE/bug-issue.yml b/.github/ISSUE_TEMPLATE/bug-issue.yml
index 193df90b46..6b98f04837 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 53b1373a16..35084c2069 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 3ed71897aa..c113646e43 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 a9008310a8..de0df6d2d9 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 f9ddf51bab..5f21d12d57 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 febfeb01f8..ac0cf22800 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,31 +318,31 @@ 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)
+### [📦 `com.ithebk.expensemanager`](https://play.google.com/store/apps/details?id=com.ithebk.expensemanager)
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
-| `unlock-pro` | Unlocks all pro features. | all |
+| `unlock-pro` | Unlocks pro features. | all |
-### [📦 `org.totschnig.myexpenses`](https://play.google.com/store/apps/details?id=org.totschnig.myexpenses)
+### [📦 `com.awedea.nyx`](https://play.google.com/store/apps/details?id=com.awedea.nyx)
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
-| `unlock-pro` | Unlocks all professional features. | 3.4.9 |
+| `unlock-pro` | Unlocks all pro features. | all |
-### [📦 `com.zombodroid.MemeGenerator`](https://play.google.com/store/apps/details?id=com.zombodroid.MemeGenerator)
+### [📦 `ginlemon.iconpackstudio`](https://play.google.com/store/apps/details?id=ginlemon.iconpackstudio)
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
-| `unlock-pro` | Unlocks pro features. | 4.6364 |
+| `unlock-pro` | Unlocks all pro features. | all |
-### [📦 `com.ithebk.expensemanager`](https://play.google.com/store/apps/details?id=com.ithebk.expensemanager)
+### [📦 `tv.trakt.trakt`](https://play.google.com/store/apps/details?id=tv.trakt.trakt)
| 💊 Patch | 📜 Description | 🏹 Target Version |
@@ -336,7 +350,7 @@ The official Patch bundle provided by ReVanced and the community.
| `unlock-pro` | Unlocks pro features. | all |
-### [📦 `ginlemon.iconpackstudio`](https://play.google.com/store/apps/details?id=ginlemon.iconpackstudio)
+### [📦 `co.windyapp.android`](https://play.google.com/store/apps/details?id=co.windyapp.android)
| 💊 Patch | 📜 Description | 🏹 Target Version |
@@ -344,12 +358,36 @@ 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)
+### [📦 `com.zombodroid.MemeGenerator`](https://play.google.com/store/apps/details?id=com.zombodroid.MemeGenerator)
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
-| `unlock-pro` | Unlocks all pro features. | all |
+| `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 dff3d309d4..722156d50a 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 20e8bde3ca..1b7355b38c 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 6bb9acbaa1..f275f8b6af 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 7c70f90c66..37b9ffcee7 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 530ca0500d..e8a951eace 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 20a7547599..de1f10d06f 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 7deff0a9cd..2835fc0b2f 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 0365284d8d..94f41526ce 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 0000000000..36c0f653c1
--- /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 0000000000..394b3c1f49
--- /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 0000000000..9905df4de4
--- /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 347c31a2d8..7366647346 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 766147aca5..f6aff11915 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 2d24a6ccca..9bfe0ba21e 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 b2e793da44..3c3617dcd0 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 34c3e94af3..ada0385157 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 945ef2ca97..8ecdb50327 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 a64808a5fa..185a9e5ad8 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 34aa826a34..c11b2e0b6f 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 1cbb579334..0aba22b1bd 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 d505347af8..b31290f703 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 0dfa62a777..0f10168c66 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 5eb220cfce..6ba2dd9584 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 205bca30ae..9de66ac2a6 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 7c0304ebb8..bc8cdc9fb1 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 bf92bccaab..b93215674a 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 be9b266ba6..19f08da0e2 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 c29b94448a..3bb5c3a385 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 0000000000..cff25ae299
--- /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 0000000000..ef01e1a5ab
--- /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 0000000000..3d577a3396
--- /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 0000000000..d25d46ed94
--- /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 9ea14f8aca..c7b6824a18 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 90b0af58d7..d03ed15272 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 2f460c6941..df2445be7d 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 29f8379dfd..aa73c1fd3d 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 eb2f74644b..9f9dddffaf 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 ffac6ed559..90daa6b62b 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 e513e941e7..0000000000
--- 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 0000000000..f8dbd2d66f
--- /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 86341a62a5..7f58d558e3 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 bb8bf0d357..c406791ed0 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 0000000000..6ba4a8902b
--- /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 0000000000..e3ec8ff907
--- /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 0000000000..1f494a4019
--- /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 7afcdae85c..8ec4e25674 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 b10c5e23e5..eefe790f0b 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 2ef2e48dcb..efa8d35be2 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 dc31381440..0000000000
--- 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 e5d137ca69..3301d2b34b 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 557ccb5a36..e251f1decc 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 1853a97c68..09fe4bc61e 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 5c5e4174bf..61a9b35a29 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 b0e8ddbd64..21207188b8 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 0000000000..64d35878ca
--- /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 ec31835bab..0000000000
--- 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 dc3fe610e5..0000000000
--- 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 90795e1f7b..9db57cff00 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 09432143b6..7d3ec982da 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 9f2f9f84e0..3df3c87e90 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 9332bd17d0..c97913c2a1 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 fcacd61d7b..2ada5625d6 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 f575dfe3a2..56e02f45d6 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 b7c82ba6fb..e6bf32d439 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 49471faa8c..7934b12704 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 2845849bc9..5a9e6778ee 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 907a4a1604..5895a5e6e1 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 778916b55a..41ff37396d 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 88aae6a284..cc656d112e 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 1917555186..97b9193e6b 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 0000000000..c6cf428865
--- /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 0000000000..ff01b38cf3
--- /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 0000000000..ef5e2a945a
--- /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 0000000000..d3c87f360f
--- /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 0000000000..ad7f2f9a16
--- /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 dccab403f5..0f019f078c 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 dc22b02c56..f5e8430d02 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 8cc8fdd9c7..d61f3539c7 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 fc252a24c9..4f68c38193 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 4f9de5d3a9..a3544cb1ce 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 667e5abcd9..30854e0c34 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 f1e8516617..d5219ff3cf 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 384530db79..39e1a71715 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 cf585dd21e..13e4d61c54 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 fb64631861..a71d6c887a 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 4e70ca8125..2a395194b3 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 9afc4eccf1..b4d0959765 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 842dcae2d3..950c258353 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 59015a6b6b..9f6de329e0 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 2e1a1eaf1a..24dd8a7ded 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 26e51a522f..fb677fcb60 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 69778a6505..b9b524d6b6 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 46f2ba697b..a2d655ab39 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 c2f1d3c515..b1e3bb5d09 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 0fcd0943d4..42cd5a0d50 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 822a2e2fbc..d193ab61dd 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 0000000000..aa619bd8c9
--- /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 0000000000..f62cfe5fcb
--- /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 0000000000..eb678d2608
--- /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 0000000000..dd8c8198e3
--- /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 0000000000..362b913350
--- /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 c85e6c92e2..76821975f1 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 8a188600ff..16455a4c55 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 56bdf62869..fc7192cc1c 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 a5cccb1c75..74cbff08b9 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 348044040b..d476288275 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 5384546a48..23debc5408 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 04c1c09b11..31ea27485e 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 ed38035ebc..f64ba6ffef 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 3256ad024e..0f7b2454ce 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 9b1197e787..8094c03f5f 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 733710b2b9..5d5bfe492b 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 6ecb63cbdb..49e02dd7a1 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 7e8ee66a3f..12ca4da9f7 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 dba6e833ed..dd69b4da16 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 0000000000..30473cf3ac
--- /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 0000000000..5bbfaeb00d
--- /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 0000000000..210a4950b4
--- /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 e7a317849c..145bc06be2 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 cf8f1f7591..ab50280a5f 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 12c5de0432..e9a77cc3bb 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 755efe696b..5c864ba8b0 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 7f55dd22f7..258db99025 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 d0f8b7214b..f700354f78 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 20c7bdb80b..0000000000
--- 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 1a63759869..6bf971dd60 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 913f31d14e..42cc4e466a 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 f976f02108..ed30aa4eb0 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 cdb2dd1775..cbee9a584b 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 eb4f86a25f..8cb634e7df 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 dda7c74ccb..811dd497e3 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 791e151621..3c93ceda6e 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 3d3f845b4b..970f7e81be 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 3752d07987..b8cb636527 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 cc533162d5..732e7fb6fc 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 7c80f5bde3..f8f1b4c8d5 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 98f0a82f62..5eb6f5aeca 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 c604c68101..8a14dc9cee 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
+
+ /**
+ * 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
+
+ jsonHookPatchFingerprintResult.mutableMethod.apply {
+ // Insert hooks right before calling buildList.
+ val insertIndex = jsonHookPatchIndex
+
+ addInstructions(
+ insertIndex,
+ """
+ sget-object v1, ${hook.descriptor}->INSTANCE:${hook.descriptor}
+ invoke-interface {v0, v1}, Ljava/util/List;->add(Ljava/lang/Object;)Z
+ """
+ )
+ }
+
+ 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"
- const val JSON_HOOK_PATCH_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/JsonHookPatch;"
+ private const val JSON_HOOK_PATCH_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/JsonHookPatch;"
- const val BASE_PATCH_CLASS_NAME = "BaseJsonHook"
+ private const val BASE_PATCH_CLASS_NAME = "BaseJsonHook"
- const val JSON_HOOK_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/$BASE_PATCH_CLASS_NAME;"
+ private const val JSON_HOOK_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/$BASE_PATCH_CLASS_NAME;"
- private lateinit var jsonHookPatchFingerprintResult: MethodFingerprintResult
+ /**
+ * 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 f2dec2a20a..4b71bc2abb 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 cdfab469ef..d44fa95e08 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 6273a26d80..36b5460149 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 cac83ff82a..196482e919 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 a6ea294fb3..d38ab48933 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 0000000000..871b6dcf04
--- /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 0000000000..1b428ba4b4
--- /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 a0eb98d7ef..31f02ab5e9 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 230f83a1e8..353aa6a4eb 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 65931d8c9a..0000000000
--- 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 0000000000..798560a764
--- /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 b6140dcc39..0000000000
--- 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 9bcc728a45..4d907a6595 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 4bcaecc3db..0000000000
--- 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 0000000000..4491d43262
--- /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 a6e9279e86..6713227a12 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 10e14d39d8..000b4b54bc 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 df42c40f24..fc46729a45 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 c015612a4f..46823e4092 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 6e60282cd1..3d0124fd41 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 9f84d2ab64..5e8525309b 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 244dbeadf8..d296b396f8 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 f628f4d0c6..4ab4a883c1 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 b0aef8f998..56a7b6893a 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 0000000000..d6d0653af0
--- /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 94d6b2cefa..3c8f3ed0b4 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 20f83effb9..0000000000
--- 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 fed7924084..b9d0dc0979 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
+
+ val instructions = method.implementation!!.instructions
+
+ // The method has more than 7 instructions.
+ if (instructions.count() < 7) return@forEach
+
+ // The 7th instruction has the opcode CONST_4.
+ val instruction = instructions.elementAt(6)
+ if (instruction.opcode != Opcode.CONST_4) return@forEach
+
+ // the literal for this instruction has to be either 1 or 2.
+ val literal = (instruction as NarrowLiteralInstruction).narrowLiteral
+
+ // Based on the literal, determine which method is which.
+ if (literal == 1) this["P"] = method
+ if (literal == 2) this["O"] = method
+ }
+ }
+ }
+
+ seekbarTappingMethods ?: return AccessibilityPlayerProgressTimeFingerprint.toErrorResult()
+
+ SeekbarTappingFingerprint.result?.let {
+ val insertIndex = it.scanResult.patternScanResult!!.endIndex - 1
+
+ it.mutableMethod.apply {
+ val thisInstanceRegister = instruction(insertIndex - 1).registerC
+
+ val freeRegister = 0
+ val xAxisRegister = 2
+
+ val pMethod = seekbarTappingMethods["P"]!!
+ val oMethod = seekbarTappingMethods["O"]!!
+
+ fun Method.toInvokeInstructionString() =
+ "invoke-virtual { v$thisInstanceRegister, v$xAxisRegister }, $definingClass->$name(I)V"
+
+ 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()
- var result = SeekbarTappingParentFingerprint.result!!
-
- val tapSeekMethods = mutableMapOf()
-
- // find the methods which tap the seekbar
- for (it in result.classDef.methods) {
- if (it.implementation == null) continue
-
- 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
-
- // we know that the 7th instruction has the opcode CONST_4
- val instruction = instructions.elementAt(6)
- if (instruction.opcode != Opcode.CONST_4) continue
-
- // the literal for this instruction has to be either 1 or 2
- val literal = (instruction as Instruction11n).narrowLiteral
-
- // method founds
- if (literal == 1) tapSeekMethods["P"] = it
- if (literal == 2) tapSeekMethods["O"] = it
- }
-
- // replace map because we don't need the upper one anymore
- result = SeekbarTappingFingerprint.result!!
-
- val implementation = result.mutableMethod.implementation!!
-
- // if tap-seeking is enabled, do not invoke the two methods below
- val pMethod = tapSeekMethods["P"]!!
- val oMethod = tapSeekMethods["O"]!!
-
- val insertIndex = result.scanResult.patternScanResult!!.endIndex + 1
-
- // 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
-
- 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 0000000000..d2281ad275
--- /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 cb86f60179..feaa5effcf 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 25e3ada235..368ba1fdd6 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 01cfffd5dc..ee1758e756 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 383eb476a9..c03a3e7f9c 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 25e3e85219..675a7369b3 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 444ffa739c..1127253581 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 cb2c94c04d..073d9b05a7 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 78a4de8836..278fb0c2fd 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 cc9c20ccc3..92d33ce317 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 2700bbad97..ff10f48f9f 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 c31480999a..849d2e18e1 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 fcd7773bec..a8aa8dbd3c 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 884e3adbc8..03f57266ad 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 2348510587..e298888c11 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 e7c62c85d8..33d384042c 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 98991910fc..4500faf65e 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 4a2f584ab6..477fdf269f 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 ae60c1aa79..98036c67e7 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 ecae5d525e..a939d9b7e3 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 b9951abd44..ead1c86589 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 d2137b01c5..1f20ff2fbe 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 1ea9cfbad5..3b22d811c5 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 8ea55f8443..1523ca1c2f 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 79874b37a2..9382220c25 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 f9ae2950e0..bebceae5f8 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 50621ee062..8193f3f7f2 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 ad3edf3ccd..b3245b815d 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 c6153f34e8..e4921df9ef 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 95fd3e7e89..af446cfe8a 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 b4c3d8363f..eb54fbdb67 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 0b5cf11822..d11423ed3f 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 ffb32092e3..f310ac764a 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 c852dc42bf..0000000000
--- 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 0000000000..27f8151f0f
--- /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 1bfb297f30..0000000000
--- 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 7e67082781..0000000000
--- 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 c16d6f82e3..5ebb44d140 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 70629074e3..f6776877b9 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 0ad96367db..1ed367227b 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 94d3b103fe..c6373f635f 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 dc639f4380..feb8301944 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 c0c561520b..47d2780101 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 0931de5f1b..55521394a2 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 9fcd0dc431..603bebdd30 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 bec34caf52..01307ad6c6 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 69adc82c6d..624e3c4eba 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 6dc3d74c59..5919bb5b63 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 0000000000..e45cafd7b5
--- /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 0000000000..6178c4c89b
--- /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 0000000000..3189e17ec9
--- /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 0000000000..be0ef5cee0
--- /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 0000000000..82deee6851
--- /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 0000000000..ea69ddbe32
--- /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 0000000000..45bddf581b
--- /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 ae7f3beeb8..8ab0a1e5cb 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 ed72bd9681..276cfbe4b0 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 30f02c1437..1d50b18dbb 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 5bc6cc043d..ede1d06429 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 917439846b..bd210bfc94 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 29cca3d036..2cffc23776 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 7e3e7b0369..1c978a7c81 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 d9c4583842..8a71676e99 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 0f258ca1b9..08f9ed020d 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 577a4da0da..d47584343b 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 47388939a9..c5aa4049c4 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 0000000000..5c580599c9
--- /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 0000000000..2669411e2f
--- /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 0000000000..b63f523021
--- /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 0000000000..0638a12dd6
--- /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 a353abda92..27abf27230 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 5e5d9fb237..4597c4da42 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 a6f443d7dd..79d0e8542f 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 044c3475ff..8d7859393e 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 0000000000..f235b62ec2
--- /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 0000000000..d5b7bd9f4a
--- /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 060073e402..0000000000
--- 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 0000000000..7907f22255
--- /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 aa4639f9e7..560e17a8ec 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 6fdfa4b842..08102a5c4f 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 0000000000..a058e84cdc
--- /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 0000000000..c53e79673d
--- /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 0000000000..2f99a2f0ba
--- /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 0000000000..2d6836b2fe
--- /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 0000000000..216d7276a8
--- /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 0000000000..70a2ebc0a0
--- /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 0000000000..6c169f2aef
--- /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 0000000000..170569b9a7
--- /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 0000000000..dcad8f43a5
--- /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 0000000000..29e3d149eb
--- /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 765783005a..c3f3c77765 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 e30f8cb5a8..635578a64f 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 0000000000..9eba5cc7c9
--- /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 b810666de8..0000000000
--- 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 84e8d8d94c..89b2786201 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 0000000000..8d11da21af
--- /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 fd691647d4..0000000000
--- 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 f149f3cf61..c6c2b3b062 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 542e4b32f9..0000000000
--- 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 4abb688e9e..0000000000
--- 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 24b1ca3631..86a2865c2a 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 6184eb0c2e..601e62b83c 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 3939bdcaca..791273ad67 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 c37a86b5fd..c05d454b4c 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 c098535748..a45ae60938 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 a8dabc9caa..bf2447c4e8 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 747d0a9471..aa0f3fcc58 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 29ab1564da..7fe768162e 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 f4e6f7801f..0000000000
--- 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 0000000000..9d5c2ec2a8
--- /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 2385aa9040..199f14889c 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 ca29b8eee3..5f5c188443 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 1a23e70469..eee7ab2a2a 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 1686c7996b..b75fddfcf3 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
+ instruction(atomicReferenceStartIndex).registerB
+
val atomicReferenceRegister =
- (instruction(atomicReferenceStartIndex + 5) as FiveRegisterInstruction).registerC
+ instruction(atomicReferenceStartIndex + 4).registerC
- val insertIndex = atomicReferenceStartIndex + 8
- val moveCharSequenceInstruction = instruction(insertIndex) as TwoRegisterInstruction
+ 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")
-
- val insertIndex = implementation!!.instructions.size - 1
- val spannedParameterRegister = (instruction(insertIndex) as OneRegisterInstruction).registerA
- val parameter = (instruction(insertIndex - 2) as BuilderInstruction35c).reference
-
- if (!parameter.toString().endsWith("Landroid/text/Spanned;"))
- return PatchResultError("Method signature parameter did not match: $parameter")
-
- 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)
+ ShortsTextViewFingerprint.result?.let {
+ it.mutableMethod.apply {
+ val patternResult = it.scanResult.patternScanResult!!
+
+ // If the field is true, the TextView is for a dislike button.
+ val isDisLikesBooleanReference = instruction(patternResult.endIndex).reference
+
+ val textViewFieldReference = // Like/Dislike button TextView field
+ instruction(patternResult.endIndex - 2).reference
+
+ // 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 41e8eb34ae..866890cbc0 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 33672c81c6..75d3373ec2 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 97cb02215b..f0a8233988 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 62bd87fe99..2894e8d633 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 0000000000..845bbff948
--- /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 0000000000..89aec9b6f6
--- /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 0237c1ec36..abae290d76 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 0000000000..752f23afa7
--- /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 0000000000..a6bc89a84a
--- /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 f1d59fb514..f805334ffd 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 0000000000..a537a12f25
--- /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 975bdfe7a1..0000000000
--- 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 822484a890..9aa72efba3 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 931fbfd568..84112ff82f 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 7c59a9ace6..c5b97a993f 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 82d01af3f3..c64f17745a 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 add8947a63..2567f3fc1f 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 88b5a92972..72b516851d 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 af2fae09c8..8be60b6a9b 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 21e9092016..ded1563eda 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 51ef60315e..26994af50e 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 98baa9d697..0000000000
--- 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 ba6e29cf5b..ffb29604f2 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 0000000000..0568876efb
--- /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 fbc8dcefad..1889ed7a88 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
+ return PatchResultSuccess()
+ }
- addInstructions(
- putColorValueIndex,
- """
- invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarColorValue()I
- move-result v$overrideRegister
- """
- )
- }
- } ?: return CreateDarkThemeSeekbarFingerprint.toErrorResult()
+ companion object : OptionsContainer() {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/theme/ThemeLithoComponentsPatch;"
- 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
+ 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.",
+ )
+ )
- 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()
- }
+ 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 INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/theme/ThemePatch;"
+ 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 cfcf75ed05..0000000000
--- 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 12d3960939..a69278309f 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()
- 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
- companion object : OptionsContainer() {
- internal var inlineTimeBarColorizedBarPlayedColorDarkId = -1L
+ val children = resourcesNode.childNodes
+ for (i in 0 until children.length) {
+ val node = children.item(i) as? Element ?: continue
- 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.",
- )
- )
+ if (node.tagName != "style") continue
- 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.",
- )
- )
+ 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()
+ }
+
+ 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 ad3f149b76..ab04bfe8d5 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 a16683b14f..c784ba8a00 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 38617967dc..08b2798da8 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 ef0dba2382..d5f279458f 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 f04329dab0..8a470352b3 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 010fd65caf..06f039393a 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 09964ba5f0..0d4425b908 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 0000000000..13e9c51b55
--- /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 0cb104f24d..f37201f865 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 f3cf363e35..5428c2a4d2 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 161f960ee5..b06a4bfa01 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 1f6d84c6d4..db5229f94b 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 44be49f995..0000000000
--- 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 7872034644..0bdca1b8aa 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 0000000000..395fd022b9
--- /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 813aaf5733..dd5868d782 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 6fb114bafd..10a9dc93d1 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 91a2724c6d..9485b3efc8 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 f7b41a2424..b1d1082792 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 ffacf0355f..78b7955664 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 0901efbbd8..b9f80a60b5 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 ec2e2b5fa0..64750c53cb 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 6a55da3b21..7d483d2761 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 0000000000..9e09979367
--- /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 f5174c1901..84c53504c3 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 101098dbae..352ed3746c 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 9a59268966..68bb5e91bf 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 257f779e21..51e6d58274 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 6a59fbcc13..88bff32b0a 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 9a9f629bda..9763d18d3f 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 ee2ad6f25c..ba8d9be8db 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 15b40d0ea3..296b6477bf 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 9df6bcf0c2..902f889432 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 91e0acb016..0bf59e7053 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 ca85a89865..89a6fa3d4e 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 1defdfe653..1317e14dc8 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 4a3244cddd..dff4ca516b 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 0eb8e9a11d..c6588b82f5 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 0000000000..259915bcaf
--- /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 75e722072e..999356376a 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 11395105fd..42a9f0afad 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 0000000000..468e8e2441
--- /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 1fceecd385..0000000000
--- 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 d57892735c..0000000000
--- 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 331389068e..8804f02c55 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"
-
- // 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
- )
- }
- }
-
- // 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")}
- """
-
- val patternScanResult = scanResult.patternScanResult!!
-
- 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
+ ) = "invoke-static { $registers }, $classDescriptor->$methodName($parameters)V"
+
+ 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.
+
+ setThemeMethod.apply {
+ // This register is returned by the setTheme method.
+ val register = instruction(returnIndex).registerA
+
+ val setThemeInstruction = getSetThemeInstructionString("v$register")
+ replaceInstruction(returnIndex, setThemeInstruction)
+ addInstruction(returnIndex + 1, "return-object v0")
+ }
+ }
+ } ?: return SetThemeFingerprint.toErrorResult()
+
+
+ // 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 4248b67785..86665f5113 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 eae4e1c024..0000000000
--- 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 541601fd1c..0000000000
--- 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 c038ba4974..0000000000
--- 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 9fb318f77c..0000000000
--- 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 63111f1046..0000000000
--- 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 37d47fee12..628499d60b 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 89cccda3c7..a3e5eedfe3 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 0000000000..29e7da0764
--- /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 979f4e8a52..0db80f8807 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 f84efbee9f..6b8ae5b018 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 6e7f876146..2ff6163dfa 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 13f82a9265..5bfa9579d1 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 648f1a7e33..edb7120708 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 fe0355d683..628421a01d 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 7e64855258..d772935b5c 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 8f2ba96634..c6d9b28791 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 2d9e98682a..89d4d16c6e 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 d04b753772..c09c69ab90 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 77f44a9ed7..1df612641b 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 0000000000..701f9974d9
--- /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 0000000000..bce667560e
--- /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 dd4597b01a..1dcdf03037 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 0000000000..965486ce51
--- /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 7e871ff609..789e422eb1 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 896b5de3e0..d69bb8406c 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 592c62fc08..a9e5906711 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 9a29d162b0..ab95b0b5bd 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 d5a03e33be..635563bf1c 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 0000000000..a079bd0f33
--- /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 0000000000..b97e92931b
--- /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 e4e3368802..4d624dab2f 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 4cb98cd4d2..30c315de82 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 0000000000..e69de29bb2
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 0000000000..ae5e53d836
--- /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 e244a298e7..31ac21e8ac 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 4895e665af..625d773df6 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 0000000000..660f7d8ad9
--- /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 bed9e90d3f..d9c51ab7cd 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 44c14a2c25..6f7da47b4a 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 bf961de7bc..4b8fbcc473 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 ed26fa039a..0b0c1a9b5f 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 09fd981179..e704e983d9 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 0a7f01a25f..4835c40483 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 85351e471c..67aba37200 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 0000000000..d62857323a
--- /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 0000000000..8452816c3f
--- /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 31ca93597f..e887fe5ce7 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 d409b544b7..0000000000
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 e27034d678..0000000000
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 c0740672fa..75802473c6 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 86c7177126..0000000000
--- 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 21ff597807..150088114e 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 31b20d9451..0000000000
--- 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 c8f014afcf..d451ce290b 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 53da895f84..0000000000
--- a/src/main/resources/theme/values-night-v31/styles.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-