diff --git a/.github/ISSUE_TEMPLATE/bug-issue.yml b/.github/ISSUE_TEMPLATE/bug-issue.yml
index 193df90b..6b98f048 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 53b1373a..35084c20 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 3ed71897..c113646e 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 a9008310..de0df6d2 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 f9ddf51b..5f21d12d 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 febfeb01..ac0cf228 100644
--- a/README.md
+++ b/README.md
@@ -1,67 +1,69 @@
-## 🧩 Patches
+## 🧩 ReVanced Patches
-The official Patch bundle provided by ReVanced and the community.
+The official ReVanced Patches.
-> Looking for the JSON variant of this? [Click here](patches.json).
+## 📋 List of patches in this repository
### [📦 `com.google.android.youtube`](https://play.google.com/store/apps/details?id=com.google.android.youtube)
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
-| `always-autorepeat` | Always repeats the playing video again. | 18.16.37 |
-| `client-spoof` | Spoofs a patched client to allow playback. | 18.16.37 |
-| `comments` | Hides components related to comments. | 18.16.37 |
-| `copy-video-url` | Adds buttons in player to copy video links. | 18.16.37 |
+| `always-autorepeat` | Always repeats the playing video again. | 18.19.35 |
+| `client-spoof` | Spoofs a patched client to allow playback. | 18.19.35 |
+| `comments` | Hides components related to comments. | 18.19.35 |
+| `copy-video-url` | Adds buttons in player to copy video links. | 18.19.35 |
| `custom-branding` | Changes the YouTube launcher icon and name to your choice (defaults to ReVanced). | all |
-| `custom-video-buffer` | Lets you change the buffers of videos. | 18.16.37 |
-| `custom-video-speed` | Adds more video speed options. | 18.16.37 |
-| `disable-auto-captions` | Disable forced captions from being automatically enabled. | 18.16.37 |
-| `disable-fullscreen-panels` | Disables video description and comments panel in fullscreen view. | 18.16.37 |
-| `disable-player-popup-panels` | Disables panels from appearing automatically when going into fullscreen (playlist or live chat). | 18.16.37 |
-| `disable-shorts-on-startup` | Disables playing YouTube Shorts when launching YouTube. | 18.16.37 |
+| `custom-video-buffer` | Lets you change the buffers of videos. | 18.19.35 |
+| `disable-auto-captions` | Disable forced captions from being automatically enabled. | 18.19.35 |
+| `disable-fullscreen-panels` | Disables video description and comments panel in fullscreen view. | 18.19.35 |
+| `disable-player-popup-panels` | Disables panels from appearing automatically when going into fullscreen (playlist or live chat). | 18.19.35 |
+| `disable-shorts-on-startup` | Disables playing YouTube Shorts when launching YouTube. | 18.19.35 |
| `disable-zoom-haptics` | Disables haptics when zooming. | all |
-| `downloads` | Enables downloading music and videos from YouTube. | 18.16.37 |
+| `downloads` | Adds a download button to the YouTube video player. | 18.19.35 |
| `enable-debugging` | Adds debugging options. | all |
-| `general-ads` | Removes general ads. | 18.16.37 |
-| `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | 18.16.37 |
-| `hide-album-cards` | Hides the album cards below the artist description. | 18.16.37 |
-| `hide-artist-card` | Hides the artist card below the searchbar. | 18.16.37 |
-| `hide-autoplay-button` | Hides the autoplay button in the video player. | 18.16.37 |
-| `hide-breaking-news-shelf` | Hides the breaking news shelf on the homepage tab. | 18.16.37 |
-| `hide-captions-button` | Hides the captions button on video player. | 18.16.37 |
+| `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | 18.19.35 |
+| `hide-ads` | Removes general ads. | 18.19.35 |
+| `hide-album-cards` | Hides the album cards below the artist description. | 18.19.35 |
+| `hide-artist-card` | Hides the artist card below the searchbar. | 18.19.35 |
+| `hide-autoplay-button` | Hides the autoplay button in the video player. | 18.19.35 |
+| `hide-breaking-news-shelf` | Hides the breaking news shelf on the homepage tab. | 18.19.35 |
+| `hide-captions-button` | Hides the captions button on video player. | 18.19.35 |
| `hide-cast-button` | Hides the cast button in the video player. | all |
-| `hide-crowdfunding-box` | Hides the crowdfunding box between the player and video description. | 18.16.37 |
-| `hide-email-address` | Hides the email address in the account switcher. | 18.16.37 |
-| `hide-endscreen-cards` | Hides the suggested video cards at the end of a video in fullscreen. | 18.16.37 |
-| `hide-floating-microphone-button` | Hides the floating microphone button which appears in search. | 18.16.37 |
-| `hide-get-premium` | Hides advertisement for YouTube Premium under the video player. | 18.16.37 |
-| `hide-info-cards` | Hides info cards in videos. | 18.16.37 |
-| `hide-player-buttons` | Adds the option to hide video player previous and next buttons. | all |
-| `hide-player-overlay` | Hides the dark player overlay when player controls are visible. | all |
-| `hide-seekbar` | Hides the seekbar. | 18.16.37 |
-| `hide-timestamp` | Hides timestamp in video player. | 18.16.37 |
-| `hide-video-action-buttons` | Adds the options to hide action buttons under a video. | 18.16.37 |
-| `hide-watch-in-vr` | Hides the option to watch in VR from the player settings flyout panel. | 18.16.37 |
-| `hide-watermark` | Hides creator's watermarks on videos. | 18.16.37 |
-| `minimized-playback` | Enables minimized and background playback. | 18.16.37 |
-| `navigation-buttons` | Adds options to hide or change navigation buttons. | 18.16.37 |
-| `old-quality-layout` | Enables the original video quality flyout in the video player settings | 18.16.37 |
-| `open-links-externally` | Open links outside of the app directly in your browser. | 18.16.37 |
+| `hide-crowdfunding-box` | Hides the crowdfunding box between the player and video description. | 18.19.35 |
+| `hide-email-address` | Hides the email address in the account switcher. | 18.19.35 |
+| `hide-endscreen-cards` | Hides the suggested video cards at the end of a video in fullscreen. | 18.19.35 |
+| `hide-filter-bar` | Hides the filter bar in video feeds. | 18.19.35 |
+| `hide-floating-microphone-button` | Hides the floating microphone button which appears in search. | 18.19.35 |
+| `hide-get-premium` | Hides advertisement for YouTube Premium under the video player. | 18.19.35 |
+| `hide-info-cards` | Hides info cards in videos. | 18.19.35 |
+| `hide-load-more-button` | Hides the button under videos that loads similar videos. | 18.19.35 |
+| `hide-player-buttons` | Adds the option to hide video player previous and next buttons. | 18.19.35 |
+| `hide-player-overlay` | Hides the dark background overlay from the player when player controls are visible. | all |
+| `hide-seekbar` | Hides the seekbar. | 18.19.35 |
+| `hide-shorts-components` | Hides components from YouTube Shorts. | 18.19.35 |
+| `hide-timestamp` | Hides timestamp in video player. | 18.19.35 |
+| `hide-video-action-buttons` | Adds the options to hide action buttons under a video. | 18.19.35 |
+| `hide-watch-in-vr` | Hides the option to watch in VR from the player settings flyout panel. | 18.19.35 |
+| `hide-watermark` | Hides creator's watermarks on videos. | 18.19.35 |
+| `minimized-playback` | Enables minimized and background playback. | 18.19.35 |
+| `navigation-buttons` | Adds options to hide or change navigation buttons. | 18.19.35 |
+| `old-quality-layout` | Enables the original video quality flyout in the video player settings. | 18.19.35 |
+| `open-links-externally` | Open links outside of the app directly in your browser. | 18.19.35 |
| `premium-heading` | Shows premium branding on the home screen. | all |
-| `remember-playback-speed` | Adds the ability to remember the playback speed you chose in the video playback speed flyout. | 18.16.37 |
-| `remember-video-quality` | Adds the ability to remember the video quality you chose in the video quality flyout. | 18.16.37 |
-| `remove-player-button-background` | Removes the background from the video player buttons. | 18.16.37 |
-| `return-youtube-dislike` | Shows the dislike count of videos using the Return YouTube Dislike API. | 18.16.37 |
-| `seekbar-tapping` | Enables tap-to-seek on the seekbar of the video player. | 18.16.37 |
-| `sponsorblock` | Integrates SponsorBlock which allows skipping video segments such as sponsored content. | 18.16.37 |
-| `spoof-app-version` | Tricks YouTube into thinking, you are running an older version of the app. One of the side effects also includes restoring the old UI. | 18.16.37 |
-| `swipe-controls` | Adds volume and brightness swipe controls. | 18.16.37 |
-| `tablet-mini-player` | Enables the tablet mini player layout. | 18.16.37 |
+| `remember-video-quality` | Adds the ability to remember the video quality you chose in the video quality flyout. | 18.19.35 |
+| `remove-player-button-background` | Removes the background from the video player buttons. | 18.19.35 |
+| `return-youtube-dislike` | Shows the dislike count of videos using the Return YouTube Dislike API. | 18.19.35 |
+| `seekbar-tapping` | Enables tap-to-seek on the seekbar of the video player. | 18.19.35 |
+| `sponsorblock` | Integrates SponsorBlock which allows skipping video segments such as sponsored content. | 18.19.35 |
+| `spoof-app-version` | Tricks YouTube into thinking, you are running an older version of the app. One of the side effects also includes restoring the old UI. | 18.19.35 |
+| `swipe-controls` | Adds volume and brightness swipe controls. | 18.19.35 |
+| `tablet-mini-player` | Enables the tablet mini player layout. | 18.19.35 |
| `theme` | Applies a custom theme. | all |
-| `vanced-microg-support` | Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG. | 18.16.37 |
-| `video-ads` | Removes ads in the video player. | 18.16.37 |
-| `wide-searchbar` | Replaces the search icon with a wide search bar. This will hide the YouTube logo when active. | 18.16.37 |
+| `vanced-microg-support` | Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG. | 18.19.35 |
+| `video-ads` | Removes ads in the video player. | 18.19.35 |
+| `video-speed` | Adds custom video speeds and ability to remember the playback speed you chose in the video playback speed flyout. | 18.19.35 |
+| `wide-searchbar` | Replaces the search icon with a wide search bar. This will hide the YouTube logo when active. | 18.19.35 |
### [📦 `com.google.android.apps.youtube.music`](https://play.google.com/store/apps/details?id=com.google.android.apps.youtube.music)
@@ -119,6 +121,7 @@ The official Patch bundle provided by ReVanced and the community.
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
+| `auto-claim-channel-points` | Automatically claim Channel Points. | all |
| `block-audio-ads` | Blocks audio ads in streams and VODs. | 14.6.1 |
| `block-embedded-ads` | Blocks embedded stream ads using services like TTV.lol or PurpleAdBlocker. | 14.6.1 |
| `block-video-ads` | Blocks video ads in streams and VODs. | 14.6.1 |
@@ -138,6 +141,17 @@ The official Patch bundle provided by ReVanced and the community.
| `hide-views-stats` | Hides the view stats under tweets. | 9.71.0-release.0 |
+### [📦 `com.reddit.frontpage`](https://play.google.com/store/apps/details?id=com.reddit.frontpage)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `hide-ads` | Removes general ads from the Reddit frontpage and subreddits. | all |
+| `hide-subreddit-banner` | Hides banner ads from comments on subreddits. | all |
+| `premium-icon-reddit` | Unlocks premium Reddit app icons. | all |
+| `sanitize-sharing-links` | Removes (tracking) query parameters from the URLs when sharing links. | all |
+
+
### [📦 `com.spotify.music`](https://play.google.com/store/apps/details?id=com.spotify.music)
@@ -148,14 +162,14 @@ The official Patch bundle provided by ReVanced and the community.
| `spotify-theme` | Applies a custom theme. | all |
-### [📦 `com.reddit.frontpage`](https://play.google.com/store/apps/details?id=com.reddit.frontpage)
+### [📦 `com.facebook.orca`](https://play.google.com/store/apps/details?id=com.facebook.orca)
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
-| `general-reddit-ads` | Removes general ads from the Reddit frontpage and subreddits. | 2023.12.0 |
-| `hide-subreddit-banner` | Hides banner ads from comments on subreddits. | 2023.12.0 |
-| `premium-icon-reddit` | Unlocks premium Reddit app icons. | all |
+| `disable-switching-emoji-to-sticker-in-message-input-field` | Disables switching from emoji to sticker search mode in message input field | all |
+| `disable-typing-indicator` | Disables the indicator while typing a message | all |
+| `hide-inbox-ads` | Hides ads in inbox. | all |
### [📦 `at.gv.bmf.bmf2go`](https://play.google.com/store/apps/details?id=at.gv.bmf.bmf2go)
@@ -176,6 +190,14 @@ The official Patch bundle provided by ReVanced and the community.
| `spoof-signature` | Spoofs the signature of the app. | all |
+### [📦 `com.laurencedawson.reddit_sync`](https://play.google.com/store/apps/details?id=com.laurencedawson.reddit_sync)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `disable-ads` | Disables ads. | all |
+
+
### [📦 `com.myprog.hexedit`](https://play.google.com/store/apps/details?id=com.myprog.hexedit)
@@ -208,14 +230,6 @@ The official Patch bundle provided by ReVanced and the community.
| `hide-ads` | Removes general ads. | all |
-### [📦 `com.facebook.orca`](https://play.google.com/store/apps/details?id=com.facebook.orca)
-
-
-| 💊 Patch | 📜 Description | 🏹 Target Version |
-|:--------:|:--------------:|:-----------------:|
-| `hide-inbox-ads` | Hides ads in inbox. | all |
-
-
### [📦 `com.instagram.android`](https://play.google.com/store/apps/details?id=com.instagram.android)
@@ -285,7 +299,7 @@ The official Patch bundle provided by ReVanced and the community.
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
-| `unlock-plus` | Unlocks plus features. | 8.9.0 |
+| `unlock-plus` | Unlocks plus features. | 8.20.0 |
### [📦 `io.yuka.android`](https://play.google.com/store/apps/details?id=io.yuka.android)
@@ -304,30 +318,6 @@ The official Patch bundle provided by ReVanced and the community.
| `unlock-prime` | Unlocks Nova Prime and all functions of the app. | all |
-### [📦 `co.windyapp.android`](https://play.google.com/store/apps/details?id=co.windyapp.android)
-
-
-| 💊 Patch | 📜 Description | 🏹 Target Version |
-|:--------:|:--------------:|:-----------------:|
-| `unlock-pro` | Unlocks all pro features. | all |
-
-
-### [📦 `org.totschnig.myexpenses`](https://play.google.com/store/apps/details?id=org.totschnig.myexpenses)
-
-
-| 💊 Patch | 📜 Description | 🏹 Target Version |
-|:--------:|:--------------:|:-----------------:|
-| `unlock-pro` | Unlocks all professional features. | 3.4.9 |
-
-
-### [📦 `com.zombodroid.MemeGenerator`](https://play.google.com/store/apps/details?id=com.zombodroid.MemeGenerator)
-
-
-| 💊 Patch | 📜 Description | 🏹 Target Version |
-|:--------:|:--------------:|:-----------------:|
-| `unlock-pro` | Unlocks pro features. | 4.6364 |
-
-
### [📦 `com.ithebk.expensemanager`](https://play.google.com/store/apps/details?id=com.ithebk.expensemanager)
@@ -336,6 +326,14 @@ The official Patch bundle provided by ReVanced and the community.
| `unlock-pro` | Unlocks pro features. | all |
+### [📦 `com.awedea.nyx`](https://play.google.com/store/apps/details?id=com.awedea.nyx)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `unlock-pro` | Unlocks all pro features. | all |
+
+
### [📦 `ginlemon.iconpackstudio`](https://play.google.com/store/apps/details?id=ginlemon.iconpackstudio)
@@ -344,7 +342,15 @@ The official Patch bundle provided by ReVanced and the community.
| `unlock-pro` | Unlocks all pro features. | all |
-### [📦 `com.awedea.nyx`](https://play.google.com/store/apps/details?id=com.awedea.nyx)
+### [📦 `tv.trakt.trakt`](https://play.google.com/store/apps/details?id=tv.trakt.trakt)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `unlock-pro` | Unlocks pro features. | all |
+
+
+### [📦 `co.windyapp.android`](https://play.google.com/store/apps/details?id=co.windyapp.android)
| 💊 Patch | 📜 Description | 🏹 Target Version |
@@ -352,6 +358,38 @@ The official Patch bundle provided by ReVanced and the community.
| `unlock-pro` | Unlocks all pro features. | all |
+### [📦 `com.zombodroid.MemeGenerator`](https://play.google.com/store/apps/details?id=com.zombodroid.MemeGenerator)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `unlock-pro` | Unlocks pro features. | 4.6377 |
+
+
+### [📦 `com.candylink.openvpn`](https://play.google.com/store/apps/details?id=com.candylink.openvpn)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `unlock-pro` | Unlocks premium features. | all |
+
+
+### [📦 `org.totschnig.myexpenses`](https://play.google.com/store/apps/details?id=org.totschnig.myexpenses)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `unlock-pro` | Unlocks all professional features. | 3.4.9 |
+
+
+### [📦 `com.vsco.cam`](https://play.google.com/store/apps/details?id=com.vsco.cam)
+
+
+| 💊 Patch | 📜 Description | 🏹 Target Version |
+|:--------:|:--------------:|:-----------------:|
+| `unlock-pro` | Unlocks pro features. | all |
+
+
### [📦 `com.ticktick.task`](https://play.google.com/store/apps/details?id=com.ticktick.task)
@@ -370,6 +408,8 @@ The official Patch bundle provided by ReVanced and the community.
+> Looking for the JSON variant of this? [Click here](patches.json).
+
## 📝 JSON Format
This section explains the JSON format for the [patches.json](patches.json) file.
@@ -428,7 +468,6 @@ Example:
"description": "Enables a custom theme.",
"version": "0.0.1",
"excluded": false,
- "deprecated": false,
"options": [
{
"key": "theme",
@@ -455,7 +494,6 @@ Example:
"description": "Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).",
"version": "0.0.1",
"excluded": false,
- "deprecated": false,
"options": [
{
"key": "appName",
diff --git a/build.gradle.kts b/build.gradle.kts
index dff3d309..722156d5 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 20e8bde3..1b7355b3 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 6bb9acba..f275f8b6 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 7c70f90c..37b9ffce 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 530ca050..e8a951ea 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 20a75475..de1f10d0 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 7deff0a9..2835fc0b 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 0365284d..94f41526 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 00000000..36c0f653
--- /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 00000000..394b3c1f
--- /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 00000000..9905df4d
--- /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 347c31a2..73666473 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 766147ac..f6aff119 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 2d24a6cc..9bfe0ba2 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 b2e793da..3c3617dc 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 34c3e94a..ada03851 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 945ef2ca..8ecdb503 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 a64808a5..185a9e5a 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 34aa826a..c11b2e0b 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 1cbb5793..0aba22b1 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 d505347a..b31290f7 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 0dfa62a7..0f10168c 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 5eb220cf..6ba2dd95 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 205bca30..9de66ac2 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 7c0304eb..bc8cdc9f 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 bf92bcca..b9321567 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 be9b266b..19f08da0 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 c29b9444..3bb5c3a3 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 00000000..cff25ae2
--- /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 00000000..ef01e1a5
--- /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 00000000..3d577a33
--- /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 00000000..d25d46ed
--- /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 9ea14f8a..c7b6824a 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 90b0af58..d03ed152 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 2f460c69..df2445be 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 29f8379d..aa73c1fd 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 eb2f7464..9f9dddff 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 ffac6ed5..90daa6b6 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 e513e941..00000000
--- 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 00000000..f8dbd2d6
--- /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 86341a62..7f58d558 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 bb8bf0d3..c406791e 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 00000000..6ba4a890
--- /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 00000000..e3ec8ff9
--- /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 00000000..1f494a40
--- /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 7afcdae8..8ec4e256 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 b10c5e23..eefe790f 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 2ef2e48d..efa8d35b 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 dc313814..00000000
--- 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 e5d137ca..3301d2b3 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 557ccb5a..e251f1de 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 1853a97c..09fe4bc6 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 5c5e4174..61a9b35a 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 b0e8ddbd..21207188 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 00000000..64d35878
--- /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 ec31835b..00000000
--- 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 dc3fe610..00000000
--- 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 90795e1f..9db57cff 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 09432143..7d3ec982 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 9f2f9f84..3df3c87e 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 9332bd17..c97913c2 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 fcacd61d..2ada5625 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 f575dfe3..56e02f45 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 b7c82ba6..e6bf32d4 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 49471faa..7934b127 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 2845849b..5a9e6778 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 907a4a16..5895a5e6 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 778916b5..41ff3739 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 88aae6a2..cc656d11 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 19175551..97b9193e 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 00000000..c6cf4288
--- /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 00000000..ff01b38c
--- /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 00000000..ef5e2a94
--- /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 00000000..d3c87f36
--- /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 00000000..ad7f2f9a
--- /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 dccab403..0f019f07 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 dc22b02c..f5e8430d 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 8cc8fdd9..d61f3539 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 fc252a24..4f68c381 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 4f9de5d3..a3544cb1 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 667e5abc..30854e0c 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 f1e85166..d5219ff3 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 384530db..39e1a717 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 cf585dd2..13e4d61c 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 fb646318..a71d6c88 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 4e70ca81..2a395194 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 9afc4ecc..b4d09597 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 842dcae2..950c2583 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 59015a6b..9f6de329 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 2e1a1eaf..24dd8a7d 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 26e51a52..fb677fcb 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 69778a65..b9b524d6 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 46f2ba69..a2d655ab 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 c2f1d3c5..b1e3bb5d 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 0fcd0943..42cd5a0d 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 822a2e2f..d193ab61 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 00000000..aa619bd8
--- /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 00000000..f62cfe5f
--- /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 00000000..eb678d26
--- /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 00000000..dd8c8198
--- /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 00000000..362b9133
--- /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 c85e6c92..76821975 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 8a188600..16455a4c 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 56bdf628..fc7192cc 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 a5cccb1c..74cbff08 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 34804404..d4762882 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 5384546a..23debc54 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 04c1c09b..31ea2748 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 ed38035e..f64ba6ff 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 3256ad02..0f7b2454 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 9b1197e7..8094c03f 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 733710b2..5d5bfe49 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 6ecb63cb..49e02dd7 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 7e8ee66a..12ca4da9 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 dba6e833..dd69b4da 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 00000000..30473cf3
--- /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 00000000..5bbfaeb0
--- /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 00000000..210a4950
--- /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 e7a31784..145bc06b 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 cf8f1f75..ab50280a 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 12c5de04..e9a77cc3 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 755efe69..5c864ba8 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 7f55dd22..258db990 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 d0f8b721..f700354f 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 20c7bdb8..00000000
--- 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 1a637598..6bf971dd 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 913f31d1..42cc4e46 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 f976f021..ed30aa4e 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 cdb2dd17..cbee9a58 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 eb4f86a2..8cb634e7 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 dda7c74c..811dd497 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 791e1516..3c93ceda 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 3d3f845b..970f7e81 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 3752d079..b8cb6365 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 cc533162..732e7fb6 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 7c80f5bd..f8f1b4c8 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 98f0a82f..5eb6f5ae 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 c604c681..8a14dc9c 100644
--- a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/patch/JsonHookPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/patch/JsonHookPatch.kt
@@ -5,13 +5,18 @@ import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.extensions.removeInstructions
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
-import app.revanced.patcher.patch.*
+import app.revanced.patcher.patch.BytecodePatch
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultError
+import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.RequiresIntegrations
import app.revanced.patches.twitter.misc.hook.json.fingerprints.JsonHookPatchFingerprint
import app.revanced.patches.twitter.misc.hook.json.fingerprints.JsonInputStreamFingerprint
import app.revanced.patches.twitter.misc.hook.json.fingerprints.LoganSquareFingerprint
+import java.io.Closeable
import java.io.InvalidClassException
@Name("json-hook")
@@ -20,16 +25,16 @@ import java.io.InvalidClassException
@RequiresIntegrations
class JsonHookPatch : BytecodePatch(
listOf(LoganSquareFingerprint)
-) {
+), Closeable {
override fun execute(context: BytecodeContext): PatchResult {
- // Make sure the integrations are present.
- val jsonHookPatch = context.findClass { it.type == JSON_HOOK_PATCH_CLASS_DESCRIPTOR }
- ?: return PatchResultError("Could not find integrations.")
+ JsonHookPatchFingerprint.also {
+ // Make sure the integrations are present.
+ val jsonHookPatch = context.findClass { classDef -> classDef.type == JSON_HOOK_PATCH_CLASS_DESCRIPTOR }
+ ?: throw PatchResultError("Could not find integrations.")
- // Allow patch to inject hooks into the patches integrations.
- jsonHookPatchFingerprintResult = JsonHookPatchFingerprint.also {
- it.resolve(context, jsonHookPatch.immutableClass)
- }.result ?: return PatchResultError("Unexpected integrations.")
+ if (!it.resolve(context, jsonHookPatch.immutableClass))
+ throw PatchResultError("Unexpected integrations.")
+ }.let { hooks = JsonHookPatchHook(it) }
// Conveniently find the type to hook a method in, via a named field.
val jsonFactory = LoganSquareFingerprint.result
@@ -64,30 +69,10 @@ class JsonHookPatch : BytecodePatch(
*
* @param context The [BytecodeContext] of the current patch.
* @param descriptor The class descriptor of the hook.
+ * @throws ClassNotFoundException If the class could not be found.
*/
- internal class Hook(context: BytecodeContext, private val descriptor: String) {
- private var added = false
-
- /**
- * Add the hook.
- */
- internal fun add() {
- if (added) return
-
- jsonHookPatchFingerprintResult.apply {
- mutableMethod.apply {
- addInstructions(
- scanResult.patternScanResult!!.startIndex,
- """
- sget-object v1, $descriptor->INSTANCE:$descriptor
- invoke-virtual {v0, v1}, Lkotlin/collections/builders/ListBuilder;->add(Ljava/lang/Object;)Z
- """
- )
- }
- }
-
- added = true
- }
+ internal class Hook(context: BytecodeContext, internal val descriptor: String) {
+ internal var added = false
init {
context.findClass { it.type == descriptor }?.let {
@@ -102,15 +87,67 @@ class JsonHookPatch : BytecodePatch(
}
}
- private companion object {
- const val JSON_HOOK_CLASS_NAMESPACE = "app/revanced/twitter/patches/hook/json"
+ /**
+ * A hook for the [JsonHookPatch].
+ *
+ * @param jsonHookPatchFingerprint The [JsonHookPatchFingerprint] to hook.
+ */
+ internal class JsonHookPatchHook(jsonHookPatchFingerprint: MethodFingerprint): Closeable {
+ private val jsonHookPatchFingerprintResult = jsonHookPatchFingerprint.result!!
+ private val jsonHookPatchIndex = jsonHookPatchFingerprintResult.scanResult.patternScanResult!!.endIndex
- const val JSON_HOOK_PATCH_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/JsonHookPatch;"
+ /**
+ * Add a hook to the [JsonHookPatch].
+ * Will not add the hook if it's already added.
+ *
+ * @param hook The [Hook] to add.
+ */
+ fun addHook(hook: Hook) {
+ if (hook.added) return
- const val BASE_PATCH_CLASS_NAME = "BaseJsonHook"
+ jsonHookPatchFingerprintResult.mutableMethod.apply {
+ // Insert hooks right before calling buildList.
+ val insertIndex = jsonHookPatchIndex
- const val JSON_HOOK_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/$BASE_PATCH_CLASS_NAME;"
+ addInstructions(
+ insertIndex,
+ """
+ sget-object v1, ${hook.descriptor}->INSTANCE:${hook.descriptor}
+ invoke-interface {v0, v1}, Ljava/util/List;->add(Ljava/lang/Object;)Z
+ """
+ )
+ }
- private lateinit var jsonHookPatchFingerprintResult: MethodFingerprintResult
+ hook.added = true
+ }
+
+ override fun close() {
+ // Remove hooks.add(dummyHook).
+ jsonHookPatchFingerprintResult.mutableMethod.apply {
+ val addDummyHookIndex = jsonHookPatchIndex - 2
+
+ removeInstructions(addDummyHookIndex, 2)
+ }
+ }
}
+
+ override fun close() = hooks.close()
+
+ internal companion object {
+ private const val JSON_HOOK_CLASS_NAMESPACE = "app/revanced/twitter/patches/hook/json"
+
+ private const val JSON_HOOK_PATCH_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/JsonHookPatch;"
+
+ private const val BASE_PATCH_CLASS_NAME = "BaseJsonHook"
+
+ private const val JSON_HOOK_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/$BASE_PATCH_CLASS_NAME;"
+
+ /**
+ * The [JsonHookPatchHook] of the [JsonHookPatch].
+ *
+ * @see JsonHookPatchHook
+ */
+ internal lateinit var hooks: JsonHookPatchHook
+ }
+
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/BaseHookPatchPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/hook/patch/BaseHookPatchPatch.kt
index f2dec2a2..4b71bc2a 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 cdfab469..d44fa95e 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 6273a26d..36b54601 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 cac83ff8..196482e9 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 a6ea294f..d38ab489 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 00000000..871b6dcf
--- /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 00000000..1b428ba4
--- /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 a0eb98d7..31f02ab5 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 230f83a1..353aa6a4 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 65931d8c..00000000
--- 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 00000000..798560a7
--- /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 b6140dcc..00000000
--- 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 9bcc728a..4d907a65 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 4bcaecc3..00000000
--- 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 00000000..4491d432
--- /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 a6e9279e..6713227a 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 10e14d39..000b4b54 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 df42c40f..fc46729a 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 c015612a..46823e40 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 6e60282c..3d0124fd 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 9f84d2ab..5e852530 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 244dbead..d296b396 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 f628f4d0..4ab4a883 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 b0aef8f9..56a7b689 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 00000000..d6d0653a
--- /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 94d6b2ce..3c8f3ed0 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 20f83eff..00000000
--- 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 fed79240..b9d0dc09 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingPatch.kt
@@ -1,110 +1,95 @@
package app.revanced.patches.youtube.interaction.seekbar.patch
+import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
-import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
+import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility
+import app.revanced.patches.youtube.interaction.seekbar.fingerprints.AccessibilityPlayerProgressTimeFingerprint
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.SeekbarTappingFingerprint
-import app.revanced.patches.youtube.interaction.seekbar.fingerprints.SeekbarTappingParentFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-import app.revanced.patches.shared.settings.preference.impl.StringResource
-import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import org.jf.dexlib2.Opcode
-import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
import org.jf.dexlib2.iface.Method
-import org.jf.dexlib2.iface.instruction.formats.Instruction11n
+import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
@Patch
-@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
+@DependsOn([IntegrationsPatch::class, EnableSeekbarTappingResourcePatch::class])
@Name("seekbar-tapping")
@Description("Enables tap-to-seek on the seekbar of the video player.")
@SeekbarTappingCompatibility
@Version("0.0.1")
class EnableSeekbarTappingPatch : BytecodePatch(
- listOf(
- SeekbarTappingParentFingerprint, SeekbarTappingFingerprint
- )
+ listOf(AccessibilityPlayerProgressTimeFingerprint, SeekbarTappingFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
- SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
- SwitchPreference(
- "revanced_enable_tap_seeking",
- StringResource("revanced_seekbar_tapping_enabled_title", "Enable seekbar tapping"),
- true,
- StringResource("revanced_seekbar_tapping_summary_on", "Seekbar tapping is enabled"),
- StringResource("revanced_seekbar_tapping_summary_off", "Seekbar tapping is disabled")
- )
- )
+ // Find the required methods to tap the seekbar.
+ val seekbarTappingMethods =
+ AccessibilityPlayerProgressTimeFingerprint.result?.classDef?.methods?.let { methods ->
+ buildMap {
+ // find the methods which tap the seekbar
+ methods.forEach { method ->
+ if (method.implementation == null) return@forEach
- var result = SeekbarTappingParentFingerprint.result!!
+ val instructions = method.implementation!!.instructions
- val tapSeekMethods = mutableMapOf()
+ // The method has more than 7 instructions.
+ if (instructions.count() < 7) return@forEach
- // find the methods which tap the seekbar
- for (it in result.classDef.methods) {
- if (it.implementation == null) continue
+ // The 7th instruction has the opcode CONST_4.
+ val instruction = instructions.elementAt(6)
+ if (instruction.opcode != Opcode.CONST_4) return@forEach
- val instructions = it.implementation!!.instructions
- // here we make sure we actually find the method because it has more than 7 instructions
- if (instructions.count() < 7) continue
+ // the literal for this instruction has to be either 1 or 2.
+ val literal = (instruction as NarrowLiteralInstruction).narrowLiteral
- // we know that the 7th instruction has the opcode CONST_4
- val instruction = instructions.elementAt(6)
- if (instruction.opcode != Opcode.CONST_4) continue
+ // Based on the literal, determine which method is which.
+ if (literal == 1) this["P"] = method
+ if (literal == 2) this["O"] = method
+ }
+ }
+ }
- // the literal for this instruction has to be either 1 or 2
- val literal = (instruction as Instruction11n).narrowLiteral
+ seekbarTappingMethods ?: return AccessibilityPlayerProgressTimeFingerprint.toErrorResult()
- // method founds
- if (literal == 1) tapSeekMethods["P"] = it
- if (literal == 2) tapSeekMethods["O"] = it
- }
+ SeekbarTappingFingerprint.result?.let {
+ val insertIndex = it.scanResult.patternScanResult!!.endIndex - 1
- // replace map because we don't need the upper one anymore
- result = SeekbarTappingFingerprint.result!!
+ it.mutableMethod.apply {
+ val thisInstanceRegister = instruction(insertIndex - 1).registerC
- val implementation = result.mutableMethod.implementation!!
+ val freeRegister = 0
+ val xAxisRegister = 2
- // if tap-seeking is enabled, do not invoke the two methods below
- val pMethod = tapSeekMethods["P"]!!
- val oMethod = tapSeekMethods["O"]!!
+ val pMethod = seekbarTappingMethods["P"]!!
+ val oMethod = seekbarTappingMethods["O"]!!
- val insertIndex = result.scanResult.patternScanResult!!.endIndex + 1
+ fun Method.toInvokeInstructionString() =
+ "invoke-virtual { v$thisInstanceRegister, v$xAxisRegister }, $definingClass->$name(I)V"
- // get the required register
- val instruction = implementation.instructions[insertIndex - 1]
- if (instruction.opcode != Opcode.INVOKE_VIRTUAL) return PatchResultError("Could not find the correct register")
- val register = (instruction as Instruction35c).registerC
+ addInstructions(
+ insertIndex,
+ """
+ invoke-static { }, Lapp/revanced/integrations/patches/SeekbarTappingPatch;->seekbarTappingEnabled()Z
+ move-result v$freeRegister
+ if-eqz v$freeRegister, :disabled
+ ${oMethod.toInvokeInstructionString()}
+ ${pMethod.toInvokeInstructionString()}
+ """,
+ listOf(ExternalLabel("disabled", instruction(insertIndex)))
+ )
+ }
+ } ?: return SeekbarTappingFingerprint.toErrorResult()
- val elseLabel = implementation.newLabelForIndex(insertIndex)
- // the instructions are written in reverse order.
- result.mutableMethod.addInstructions(
- insertIndex, """
- invoke-virtual { v$register, v2 }, ${oMethod.definingClass}->${oMethod.name}(I)V
- invoke-virtual { v$register, v2 }, ${pMethod.definingClass}->${pMethod.name}(I)V
- """
- )
-
- // if tap-seeking is disabled, do not invoke the two methods above by jumping to the else label
- implementation.addInstruction(
- insertIndex, BuilderInstruction21t(Opcode.IF_EQZ, 0, elseLabel)
- )
- result.mutableMethod.addInstructions(
- insertIndex, """
- invoke-static { }, Lapp/revanced/integrations/patches/SeekbarTappingPatch;->isTapSeekingEnabled()Z
- move-result v0
- """
- )
return PatchResultSuccess()
}
-}
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingResourcePatch.kt
new file mode 100644
index 00000000..d2281ad2
--- /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 cb86f601..feaa5eff 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 25e3ada2..368ba1fd 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 01cfffd5..ee1758e7 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 383eb476..c03a3e7f 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 25e3e852..675a7369 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 444ffa73..11272535 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 cb2c94c0..073d9b05 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 78a4de88..278fb0c2 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 cc9c20cc..92d33ce3 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 2700bbad..ff10f48f 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 c3148099..849d2e18 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 fcd7773b..a8aa8dbd 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 884e3adb..03f57266 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 23485105..e298888c 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 e7c62c85..33d38404 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 98991910..4500faf6 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 4a2f584a..477fdf26 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 ae60c1aa..98036c67 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 ecae5d52..a939d9b7 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 b9951abd..ead1c865 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 d2137b01..1f20ff2f 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 1ea9cfba..3b22d811 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 8ea55f84..1523ca1c 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 79874b37..9382220c 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 f9ae2950..bebceae5 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 50621ee0..8193f3f7 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 ad3edf3c..b3245b81 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 c6153f34..e4921df9 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 95fd3e7e..af446cfe 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 b4c3d836..eb54fbdb 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 0b5cf118..d11423ed 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 ffb32092..f310ac76 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 c852dc42..00000000
--- 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 00000000..27f8151f
--- /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 1bfb297f..00000000
--- 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 7e670827..00000000
--- 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 c16d6f82..5ebb44d1 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 70629074..f6776877 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 0ad96367..1ed36722 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 94d3b103..c6373f63 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 dc639f43..feb83019 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 c0c56152..47d27801 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 0931de5f..55521394 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 9fcd0dc4..603bebdd 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 bec34caf..01307ad6 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 69adc82c..624e3c4e 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 6dc3d74c..5919bb5b 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 00000000..e45cafd7
--- /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 00000000..6178c4c8
--- /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 00000000..3189e17e
--- /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 00000000..be0ef5ce
--- /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 00000000..82deee68
--- /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 00000000..ea69ddbe
--- /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 00000000..45bddf58
--- /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 ae7f3bee..8ab0a1e5 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 ed72bd96..276cfbe4 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 30f02c14..1d50b18d 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 5bc6cc04..ede1d064 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 91743984..bd210bfc 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 29cca3d0..2cffc237 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 7e3e7b03..1c978a7c 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 d9c45838..8a71676e 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 0f258ca1..08f9ed02 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 577a4da0..d4758434 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 47388939..c5aa4049 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 00000000..5c580599
--- /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 00000000..2669411e
--- /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 00000000..b63f5230
--- /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 00000000..0638a12d
--- /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 a353abda..27abf272 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 5e5d9fb2..4597c4da 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 a6f443d7..79d0e854 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 044c3475..8d785939 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 00000000..f235b62e
--- /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 00000000..d5b7bd9f
--- /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 060073e4..00000000
--- 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 00000000..7907f222
--- /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 aa4639f9..560e17a8 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 6fdfa4b8..08102a5c 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 00000000..a058e84c
--- /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 00000000..c53e7967
--- /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 00000000..2f99a2f0
--- /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 00000000..2d6836b2
--- /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 00000000..216d7276
--- /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 00000000..70a2ebc0
--- /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 00000000..6c169f2a
--- /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 00000000..170569b9
--- /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 00000000..dcad8f43
--- /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 00000000..29e3d149
--- /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 76578300..c3f3c777 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 e30f8cb5..635578a6 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 00000000..9eba5cc7
--- /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 b810666d..00000000
--- 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 84e8d8d9..89b27862 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 00000000..8d11da21
--- /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 fd691647..00000000
--- 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 f149f3cf..c6c2b3b0 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 542e4b32..00000000
--- 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 4abb688e..00000000
--- 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 24b1ca36..86a2865c 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 6184eb0c..601e62b8 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 3939bdca..791273ad 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 c37a86b5..c05d454b 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 c0985357..a45ae609 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 a8dabc9c..bf2447c4 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 747d0a94..aa0f3fcc 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 29ab1564..7fe76816 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 f4e6f780..00000000
--- 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 00000000..9d5c2ec2
--- /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 2385aa90..199f1488 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 ca29b8ee..5f5c1884 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 1a23e704..eee7ab2a 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 1686c799..b75fddfc 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt
@@ -5,7 +5,6 @@ import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.data.toMethodWalker
import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.addInstructions
@@ -19,14 +18,12 @@ import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.*
import app.revanced.patches.youtube.layout.returnyoutubedislike.resource.patch.ReturnYouTubeDislikeResourcePatch
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch
-import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch
-import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
+import app.revanced.patches.youtube.video.videoid.patch.VideoIdPatch
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
@@ -48,7 +45,7 @@ import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
class ReturnYouTubeDislikePatch : BytecodePatch(
listOf(
TextComponentConstructorFingerprint,
- ShortsTextComponentParentFingerprint,
+ ShortsTextViewFingerprint,
DislikesOldLayoutTextViewFingerprint,
LikeFingerprint,
DislikeFingerprint,
@@ -102,18 +99,21 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
val atomicReferenceStartIndex = TextComponentAtomicReferenceFingerprint.result!!
.scanResult.patternScanResult!!.startIndex
+ val insertIndex = atomicReferenceStartIndex + 7
+
textComponentContextFingerprintResult.mutableMethod.apply {
// Get the conversion context obfuscated field name, and the registers for the AtomicReference and CharSequence
val conversionContextFieldReference =
- (instruction(conversionContextIndex) as ReferenceInstruction).reference
+ instruction(conversionContextIndex).reference
+
// any free register
val contextRegister =
- (instruction(atomicReferenceStartIndex) as TwoRegisterInstruction).registerB
- val atomicReferenceRegister =
- (instruction(atomicReferenceStartIndex + 5) as FiveRegisterInstruction).registerC
+ instruction(atomicReferenceStartIndex).registerB
- val insertIndex = atomicReferenceStartIndex + 8
- val moveCharSequenceInstruction = instruction(insertIndex) as TwoRegisterInstruction
+ val atomicReferenceRegister =
+ instruction(atomicReferenceStartIndex + 4).registerC
+
+ val moveCharSequenceInstruction = instruction(insertIndex)
val charSequenceRegister = moveCharSequenceInstruction.registerB
// Insert as first instructions at the control flow label.
@@ -134,35 +134,40 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
// region Hook for Short videos.
- ShortsTextComponentParentFingerprint.result?.let {
- context
- .toMethodWalker(it.method)
- .nextMethod(it.scanResult.patternScanResult!!.endIndex, true)
- .getMethod().let { method ->
- with(method as MutableMethod) {
- // After walking, verify the found method is what's expected.
- if (returnType != ("Ljava/lang/CharSequence;") || parameterTypes.size != 1)
- return PatchResultError("Method signature did not match: $this $parameterTypes")
+ ShortsTextViewFingerprint.result?.let {
+ it.mutableMethod.apply {
+ val patternResult = it.scanResult.patternScanResult!!
- val insertIndex = implementation!!.instructions.size - 1
- val spannedParameterRegister = (instruction(insertIndex) as OneRegisterInstruction).registerA
- val parameter = (instruction(insertIndex - 2) as BuilderInstruction35c).reference
+ // If the field is true, the TextView is for a dislike button.
+ val isDisLikesBooleanReference = instruction(patternResult.endIndex).reference
- if (!parameter.toString().endsWith("Landroid/text/Spanned;"))
- return PatchResultError("Method signature parameter did not match: $parameter")
+ val textViewFieldReference = // Like/Dislike button TextView field
+ instruction(patternResult.endIndex - 2).reference
- insertShorts(insertIndex, spannedParameterRegister)
- }
- }
-
- // Additional hook, called after user dislikes.
- with(it.mutableMethod) {
- val insertIndex = it.scanResult.patternScanResult!!.startIndex + 2
- val overwriteRegister = (implementation!!.instructions.elementAt(insertIndex - 1)
- as OneRegisterInstruction).registerA
- insertShorts(insertIndex, overwriteRegister)
+ // Check if the hooked TextView object is that of the dislike button.
+ // If RYD is disabled, or the TextView object is not that of the dislike button, the execution flow is not interrupted.
+ // Otherwise, the TextView object is modified, and the execution flow is interrupted to prevent it from being changed afterward.
+ val insertIndex = patternResult.startIndex + 6
+ addInstructions(
+ insertIndex, """
+ # Check, if the TextView is for a dislike button
+ iget-boolean v0, p0, $isDisLikesBooleanReference
+ if-eqz v0, :is_like
+
+ # Hook the TextView, if it is for the dislike button
+ iget-object v0, p0, $textViewFieldReference
+ invoke-static {v0}, $INTEGRATIONS_CLASS_DESCRIPTOR->setShortsDislikes(Landroid/view/View;)Z
+ move-result v0
+ if-eqz v0, :ryd_disabled
+ return-void
+
+ :is_like
+ :ryd_disabled
+ nop
+ """
+ )
}
- } ?: return ShortsTextComponentParentFingerprint.toErrorResult()
+ } ?: return ShortsTextViewFingerprint.toErrorResult()
// endregion
@@ -171,9 +176,12 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
DislikesOldLayoutTextViewFingerprint.result?.let {
it.mutableMethod.apply {
val startIndex = it.scanResult.patternScanResult!!.startIndex
- val resourceIdentifierRegister = (instruction(startIndex) as OneRegisterInstruction).registerA
- val textViewRegister = (instruction(startIndex + 4) as OneRegisterInstruction).registerA
- addInstruction(startIndex + 4,
+
+ val resourceIdentifierRegister = instruction(startIndex).registerA
+ val textViewRegister = instruction(startIndex + 4).registerA
+
+ addInstruction(
+ startIndex + 4,
"invoke-static {v$resourceIdentifierRegister, v$textViewRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->setOldUILayoutDislikes(ILandroid/widget/TextView;)V"
)
}
@@ -195,14 +203,5 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
DISLIKE(-1),
REMOVE_LIKE(0)
}
-
- private fun MutableMethod.insertShorts(index: Int, register: Int) {
- addInstructions(
- index, """
- invoke-static {v$register}, $INTEGRATIONS_CLASS_DESCRIPTOR->onShortsComponentCreated(Landroid/text/Spanned;)Landroid/text/Spanned;
- move-result-object v$register
- """
- )
- }
}
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/resource/patch/ReturnYouTubeDislikeResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/resource/patch/ReturnYouTubeDislikeResourcePatch.kt
index 41e8eb34..866890cb 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 33672c81..75d3373e 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 97cb0221..f0a82339 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 62bd87fe..2894e8d6 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 00000000..845bbff9
--- /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 00000000..89aec9b6
--- /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 0237c1ec..abae290d 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 00000000..752f23af
--- /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 00000000..a6bc89a8
--- /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 f1d59fb5..f805334f 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 00000000..a537a12f
--- /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 975bdfe7..00000000
--- 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 822484a8..9aa72efb 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 931fbfd5..84112ff8 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 7c59a9ac..c5b97a99 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 82d01af3..c64f1774 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 add8947a..2567f3fc 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 88b5a929..72b51685 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 af2fae09..8be60b6a 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 21e90920..ded1563e 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 51ef6031..26994af5 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 98baa9d6..00000000
--- 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 ba6e29cf..ffb29604 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 00000000..0568876e
--- /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 fbc8dcef..1889ed7a 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/ThemeBytecodePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/ThemeBytecodePatch.kt
@@ -1,77 +1,58 @@
package app.revanced.patches.youtube.layout.theme.bytecode.patch
-import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
-import app.revanced.patcher.data.toMethodWalker
-import app.revanced.patcher.extensions.addInstructions
-import app.revanced.patcher.extensions.instruction
-import app.revanced.patcher.patch.BytecodePatch
-import app.revanced.patcher.patch.PatchResult
-import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
-import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
+import app.revanced.patches.youtube.layout.seekbar.bytecode.patch.SeekbarColorBytecodePatch
import app.revanced.patches.youtube.layout.theme.annotations.ThemeCompatibility
-import app.revanced.patches.youtube.layout.theme.bytecode.fingerprints.CreateDarkThemeSeekbarFingerprint
-import app.revanced.patches.youtube.layout.theme.bytecode.fingerprints.CreateDarkThemeSeekbarFingerprint.indexOfInstructionWithSeekbarId
-import app.revanced.patches.youtube.layout.theme.bytecode.fingerprints.SetSeekbarClickedColorFingerprint
import app.revanced.patches.youtube.layout.theme.resource.ThemeResourcePatch
-import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
-import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
@Patch
@Name("theme")
@Description("Applies a custom theme.")
-@DependsOn([ThemeLithoComponentsPatch::class, ThemeResourcePatch::class, IntegrationsPatch::class])
+@DependsOn([LithoColorHookPatch::class, SeekbarColorBytecodePatch::class, ThemeResourcePatch::class])
@ThemeCompatibility
@Version("0.0.1")
-class ThemeBytecodePatch : BytecodePatch(
- listOf(CreateDarkThemeSeekbarFingerprint, SetSeekbarClickedColorFingerprint)
-) {
+class ThemeBytecodePatch : BytecodePatch() {
+
override fun execute(context: BytecodeContext): PatchResult {
- CreateDarkThemeSeekbarFingerprint.result?.let {
- val putColorValueIndex = it.method.indexOfInstructionWithSeekbarId!! + 3
+ LithoColorHookPatch.lithoColorOverrideHook(INTEGRATIONS_CLASS_DESCRIPTOR, "getValue")
- it.mutableMethod.apply {
- val overrideRegister = (instruction(putColorValueIndex) as TwoRegisterInstruction).registerA
-
- addInstructions(
- putColorValueIndex,
- """
- invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarColorValue()I
- move-result v$overrideRegister
- """
- )
- }
- } ?: return CreateDarkThemeSeekbarFingerprint.toErrorResult()
-
- SetSeekbarClickedColorFingerprint.result?.let { result ->
- result.mutableMethod.let {
- val setColorMethodIndex = result.scanResult.patternScanResult!!.startIndex + 1
- val method = context
- .toMethodWalker(it)
- .nextMethod(setColorMethodIndex, true)
- .getMethod() as MutableMethod
-
- method.apply {
- val colorRegister = (method.instruction(0) as TwoRegisterInstruction).registerA
- addInstructions(
- 0,
- """
- invoke-static { v$colorRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarClickedColorValue(I)I
- move-result v$colorRegister
- """
- )
- }
- }
- } ?: return SetSeekbarClickedColorFingerprint.toErrorResult()
return PatchResultSuccess()
}
- private companion object {
- private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/theme/ThemePatch;"
+ companion object : OptionsContainer() {
+ private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/theme/ThemeLithoComponentsPatch;"
+
+ var darkThemeBackgroundColor: String? by option(
+ PatchOption.StringOption(
+ key = "darkThemeBackgroundColor",
+ default = "@android:color/black",
+ title = "Background color for the dark theme",
+ description = "The background color of the dark theme. Can be a hex color or a resource reference.",
+ )
+ )
+
+ var lightThemeBackgroundColor: String? by option(
+ PatchOption.StringOption(
+ key = "lightThemeBackgroundColor",
+ default = "@android:color/white",
+ title = "Background color for the light theme",
+ description = "The background color of the light theme. Can be a hex color or a resource reference.",
+ )
+ )
+
+ var splashScreenBackgroundColor: String? by option(
+ PatchOption.StringOption(
+ key = "splashScreenBackgroundColor",
+ default = "@android:color/black",
+ title = "Background color for the splash screen",
+ description = "The background color of the splash screen. Can be a hex color or a resource reference.",
+ )
+ )
}
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/ThemeLithoComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/bytecode/patch/ThemeLithoComponentsPatch.kt
deleted file mode 100644
index cfcf75ed..00000000
--- 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 12d39609..a6927830 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/resource/ThemeResourcePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/resource/ThemeResourcePatch.kt
@@ -1,15 +1,18 @@
package app.revanced.patches.youtube.layout.theme.resource
import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.*
+import app.revanced.patcher.patch.PatchResult
+import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.InputType
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.TextPreference
+import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.darkThemeBackgroundColor
+import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.lightThemeBackgroundColor
+import app.revanced.patches.youtube.layout.theme.bytecode.patch.ThemeBytecodePatch.Companion.splashScreenBackgroundColor
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
-import app.revanced.util.resources.ResourceUtils
-import app.revanced.util.resources.ResourceUtils.copyResources
import org.w3c.dom.Element
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
@@ -19,73 +22,88 @@ class ThemeResourcePatch : ResourcePatch {
TextPreference(
"revanced_seekbar_color",
StringResource("revanced_seekbar_color_title", "Seekbar color"),
- InputType.STRING,
- "#ffff0000",
StringResource(
"revanced_seekbar_color_summary",
- "The color of the seekbar for the dark theme."
- )
+ "The color of the seekbar"
+ ),
+ InputType.TEXT_CAP_CHARACTERS
),
)
- // Edit theme colors via bytecode.
- // For that the resource id is used in a bytecode patch to change the color.
-
- inlineTimeBarColorizedBarPlayedColorDarkId = ResourceMappingPatch.resourceMappings
- .find { it.name == "inline_time_bar_colorized_bar_played_color_dark" }?.id
- ?: return PatchResultError("Could not find seekbar resource")
-
-
- val darkThemeBackgroundColor = darkThemeBackgroundColor!!
- val lightThemeBackgroundColor = lightThemeBackgroundColor!!
-
// Edit theme colors via resources.
context.xmlEditor["res/values/colors.xml"].use { editor ->
val resourcesNode = editor.file.getElementsByTagName("resources").item(0) as Element
- for (i in 0 until resourcesNode.childNodes.length) {
- val node = resourcesNode.childNodes.item(i) as? Element ?: continue
+ val children = resourcesNode.childNodes
+ for (i in 0 until children.length) {
+ val node = children.item(i) as? Element ?: continue
node.textContent = when (node.getAttribute("name")) {
"yt_black0", "yt_black1", "yt_black1_opacity95", "yt_black1_opacity98", "yt_black2", "yt_black3",
"yt_black4", "yt_status_bar_background_dark", "material_grey_850" -> darkThemeBackgroundColor
+ ?: continue
"yt_white1", "yt_white1_opacity95", "yt_white1_opacity98",
"yt_white2", "yt_white3", "yt_white4",
- -> lightThemeBackgroundColor
+ -> lightThemeBackgroundColor ?: continue
else -> continue
}
}
}
- // Copy the resource file to change the splash screen color.
- context.copyResources(
- "theme", ResourceUtils.ResourceGroup("values-night-v31", "styles.xml")
- )
+ splashScreenBackgroundColor ?: return PatchResultSuccess()
+
+ // Edit splash screen background color for Android 11 and below.
+ context.xmlEditor["res/values/styles.xml"].use {
+ val resourcesNode = it.file.getElementsByTagName("resources").item(0) as Element
+
+ val children = resourcesNode.childNodes
+ for (i in 0 until children.length) {
+ val node = children.item(i) as? Element ?: continue
+
+ if (node.tagName != "style") continue
+
+ val name = node.getAttribute("name")
+ if (name != LAUNCHER_STYLE_NAME) continue
+
+ it.file.createElement("item").apply {
+ setAttribute("name", "android:windowSplashScreenBackground")
+ textContent = splashScreenBackgroundColor
+ }.also(node::appendChild)
+
+ break
+ }
+ }
+
+ // Edit splash screen background color for Android 12+.
+
+ // Add the splash screen background color to the colors.xml file.
+ context.xmlEditor["res/values/colors.xml"].use {
+ val resourcesNode = it.file.getElementsByTagName("resources").item(0) as Element
+
+ it.file.createElement("color").apply {
+ setAttribute("name", COLOR_NAME)
+ setAttribute("category", "color")
+ textContent = splashScreenBackgroundColor
+ }.also(resourcesNode::appendChild)
+ }
+
+ // Point to the splash screen background color.
+ context.xmlEditor["res/drawable/quantum_launchscreen_youtube.xml"].use {
+ val node = it.file.getElementsByTagName("layer-list").item(0) as Element
+
+ val backgroundColorItem = node.childNodes.item(1) as Element
+ backgroundColorItem.apply {
+ setAttribute("android:drawable", "@color/$COLOR_NAME")
+ }
+ }
return PatchResultSuccess()
}
- companion object : OptionsContainer() {
- internal var inlineTimeBarColorizedBarPlayedColorDarkId = -1L
-
- var darkThemeBackgroundColor: String? by option(
- PatchOption.StringOption(
- key = "darkThemeBackgroundColor",
- default = "@android:color/black",
- title = "Background color for the dark theme",
- description = "The background color of the dark theme. Can be a hex color or a resource reference.",
- )
- )
-
- var lightThemeBackgroundColor: String? by option(
- PatchOption.StringOption(
- key = "lightThemeBackgroundColor",
- default = "@android:color/white",
- title = "Background color for the light theme",
- description = "The background color of the light theme. Can be a hex color or a resource reference.",
- )
- )
+ private companion object {
+ private const val LAUNCHER_STYLE_NAME = "Base.Theme.YouTube.Launcher"
+ private const val COLOR_NAME = "splash_background_color"
}
-}
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/annotations/AutoRepeatCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/annotations/AutoRepeatCompatibility.kt
index ad3f149b..ab04bfe8 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 a16683b1..c784ba8a 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 38617967..08b2798d 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 ef0dba23..d5f27945 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 f04329da..8a470352 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 010fd65c..06f03939 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 09964ba5..0d4425b9 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 00000000..13e9c51b
--- /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 0cb104f2..f37201f8 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 f3cf363e..5428c2a4 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 161f960e..b06a4bfa 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 1f6d84c6..db5229f9 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 44be49f9..00000000
--- 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 78720346..0bdca1b8 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 00000000..395fd022
--- /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 813aaf57..dd5868d7 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 6fb114ba..10a9dc93 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 91a2724c..9485b3ef 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 f7b41a24..b1d10827 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 ffacf035..78b79556 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 0901efbb..b9f80a60 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 ec2e2b5f..64750c53 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 6a55da3b..7d483d27 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 00000000..9e099793
--- /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 f5174c19..84c53504 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 101098db..352ed374 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 9a592689..68bb5e91 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 257f779e..51e6d582 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 6a59fbcc..88bff32b 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 9a9f629b..9763d18d 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 ee2ad6f2..ba8d9be8 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 15b40d0e..296b6477 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 9df6bcf0..902f8894 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 91e0acb0..0bf59e70 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 ca85a898..89a6fa3d 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 1defdfe6..1317e14d 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 4a3244cd..dff4ca51 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 0eb8e9a1..c6588b82 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 00000000..259915bc
--- /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 75e72207..99935637 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 11395105..42a9f0af 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 00000000..468e8e24
--- /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 1fceecd3..00000000
--- 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 d5789273..00000000
--- 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 33138906..8804f02c 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/patch/SettingsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/patch/SettingsPatch.kt
@@ -7,6 +7,8 @@ import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.addInstructions
+import app.revanced.patcher.extensions.instruction
+import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
@@ -15,78 +17,61 @@ import app.revanced.patches.shared.settings.preference.impl.Preference
import app.revanced.patches.shared.settings.util.AbstractPreferenceScreen
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.LicenseActivityFingerprint
-import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.ThemeSetterAppFingerprint
-import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.ThemeSetterSystemFingerprint
+import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.SetThemeFingerprint
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourcePatch
+import org.jf.dexlib2.Opcode
+import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.util.MethodUtil
-@DependsOn(
- [
- IntegrationsPatch::class,
- SettingsResourcePatch::class,
- ]
-)
+@DependsOn([IntegrationsPatch::class, SettingsResourcePatch::class, ])
@Name("settings")
@Description("Adds settings for ReVanced to YouTube.")
@Version("0.0.1")
class SettingsPatch : BytecodePatch(
- listOf(LicenseActivityFingerprint, ThemeSetterSystemFingerprint, ThemeSetterAppFingerprint)
+ listOf(LicenseActivityFingerprint, SetThemeFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
- fun buildInvokeInstructionsString(
+ // TODO: Remove this when it is only required at one place.
+ fun getSetThemeInstructionString(
registers: String = "v0",
classDescriptor: String = THEME_HELPER_DESCRIPTOR,
methodName: String = SET_THEME_METHOD_NAME,
parameters: String = "Ljava/lang/Object;"
- ) = "invoke-static {$registers}, $classDescriptor->$methodName($parameters)V"
+ ) = "invoke-static { $registers }, $classDescriptor->$methodName($parameters)V"
- // apply the current theme of the settings page
- ThemeSetterSystemFingerprint.result!!.let { result ->
- val call = buildInvokeInstructionsString()
- result.mutableMethod.apply {
- addInstruction(
- result.scanResult.patternScanResult!!.startIndex, call
- )
- addInstructions(
- implementation!!.instructions.size - 1, call
- )
- }
- }
+ SetThemeFingerprint.result?.mutableMethod?.let { setThemeMethod ->
+ setThemeMethod.implementation!!.instructions.mapIndexedNotNull { i, instruction ->
+ if (instruction.opcode == Opcode.RETURN_OBJECT) i else null
+ }
+ .asReversed() // Prevent index shifting.
+ .forEach { returnIndex ->
+ // The following strategy is to replace the return instruction with the setTheme instruction,
+ // then add a return instruction after the setTheme instruction.
+ // This is done because the return instruction is a target of another instruction.
- // set the theme based on the preference of the app
- ThemeSetterAppFingerprint.result?.apply {
- fun buildInstructionsString(theme: Int) = """
- const/4 v0, 0x$theme
- ${buildInvokeInstructionsString(parameters = "I")}
- """
+ setThemeMethod.apply {
+ // This register is returned by the setTheme method.
+ val register = instruction(returnIndex).registerA
- val patternScanResult = scanResult.patternScanResult!!
+ val setThemeInstruction = getSetThemeInstructionString("v$register")
+ replaceInstruction(returnIndex, setThemeInstruction)
+ addInstruction(returnIndex + 1, "return-object v0")
+ }
+ }
+ } ?: return SetThemeFingerprint.toErrorResult()
- mutableMethod.apply {
- addInstructions(
- patternScanResult.endIndex + 1, buildInstructionsString(1)
- )
- addInstructions(
- patternScanResult.endIndex - 7, buildInstructionsString(0)
- )
- addInstructions(
- patternScanResult.endIndex - 9, buildInstructionsString(1)
- )
- addInstructions(
- implementation!!.instructions.size - 2, buildInstructionsString(0)
- )
- }
- } ?: return ThemeSetterAppFingerprint.toErrorResult()
- // set the theme based on the preference of the device
+ // Modify the license activity and remove all existing layout code.
+ // Must modify an existing activity and cannot add a new activity to the manifest,
+ // as that fails for root installations.
LicenseActivityFingerprint.result!!.apply licenseActivity@{
mutableMethod.apply {
fun buildSettingsActivityInvokeString(
registers: String = "p0",
classDescriptor: String = SETTINGS_ACTIVITY_DESCRIPTOR,
methodName: String = "initializeSettings",
- parameters: String = this@licenseActivity.mutableClass.type
- ) = buildInvokeInstructionsString(registers, classDescriptor, methodName, parameters)
+ parameters: String = "Landroid/app/Activity;"
+ ) = getSetThemeInstructionString(registers, classDescriptor, methodName, parameters)
// initialize the settings
addInstructions(
@@ -95,9 +80,6 @@ class SettingsPatch : BytecodePatch(
return-void
"""
)
-
- // set the current theme
- addInstruction(0, buildSettingsActivityInvokeString(methodName = "setTheme"))
}
// remove method overrides
@@ -106,14 +88,13 @@ class SettingsPatch : BytecodePatch(
}
}
+
return PatchResultSuccess()
}
internal companion object {
private const val INTEGRATIONS_PACKAGE = "app/revanced/integrations"
-
private const val SETTINGS_ACTIVITY_DESCRIPTOR = "L$INTEGRATIONS_PACKAGE/settingsmenu/ReVancedSettingActivity;"
-
private const val THEME_HELPER_DESCRIPTOR = "L$INTEGRATIONS_PACKAGE/utils/ThemeHelper;"
private const val SET_THEME_METHOD_NAME = "setTheme"
@@ -128,6 +109,15 @@ class SettingsPatch : BytecodePatch(
fun renameIntentsTargetPackage(newPackage: String) {
SettingsResourcePatch.overrideIntentsTargetPackage = newPackage
}
+
+ /**
+ * Creates an intent to open ReVanced settings of the given name
+ */
+ fun createReVancedSettingsIntent(settingsName: String) = Preference.Intent(
+ "com.google.android.youtube",
+ settingsName,
+ "com.google.android.libraries.social.licenses.LicenseActivity"
+ )
}
/**
@@ -137,6 +127,7 @@ class SettingsPatch : BytecodePatch(
val ADS = Screen("ads", "Ads", "Ad related settings")
val INTERACTIONS = Screen("interactions", "Interaction", "Settings related to interactions")
val LAYOUT = Screen("layout", "Layout", "Settings related to the layout")
+ val VIDEO = Screen("video", "Video", "Settings related to the video player")
val MISC = Screen("misc", "Misc", "Miscellaneous patches")
override fun commit(screen: app.revanced.patches.shared.settings.preference.impl.PreferenceScreen) {
diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/resource/patch/SettingsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/resource/patch/SettingsResourcePatch.kt
index 4248b677..86665f51 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 eae4e1c0..00000000
--- 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 541601fd..00000000
--- 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 c038ba49..00000000
--- 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 9fb318f7..00000000
--- 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 63111f10..00000000
--- 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 37d47fee..628499d6 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 89cccda3..a3e5eedf 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 00000000..29e7da07
--- /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 979f4e8a..0db80f88 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 f84efbee..6b8ae5b0 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 6e7f8761..2ff6163d 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 13f82a92..5bfa9579 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 648f1a7e..edb71207 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 fe0355d6..628421a0 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 7e648552..d772935b 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 8f2ba966..c6d9b287 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 2d9e9868..89d4d16c 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 d04b7537..c09c69ab 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 77f44a9e..1df61264 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 00000000..701f9974
--- /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 00000000..bce66756
--- /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 dd4597b0..1dcdf030 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 00000000..965486ce
--- /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 7e871ff6..789e422e 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 896b5de3..d69bb840 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 592c62fc..a9e59067 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 9a29d162..ab95b0b5 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 d5a03e33..635563bf 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 00000000..a079bd0f
--- /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 00000000..b97e9293
--- /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 e4e33688..4d624dab 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 4cb98cd4..30c315de 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 00000000..e69de29b
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 00000000..ae5e53d8
--- /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 e244a298..31ac21e8 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 4895e665..625d773d 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 00000000..660f7d8a
--- /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 bed9e90d..d9c51ab7 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 44c14a2c..6f7da47b 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 bf961de7..4b8fbcc4 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 ed26fa03..0b0c1a9b 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 09fd9811..e704e983 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 0a7f01a2..4835c404 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 85351e47..67aba372 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 00000000..d6285732
--- /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 00000000..8452816c
--- /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 31ca9359..e887fe5c 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 d409b544..00000000
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 e27034d6..00000000
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 c0740672..75802473 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 86c71771..00000000
--- 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 21ff5978..15008811 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 31b20d94..00000000
--- 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 c8f014af..d451ce29 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 53da895f..00000000
--- a/src/main/resources/theme/values-night-v31/styles.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-