diff --git a/.github/workflows/sync_crowdin.yml b/.github/workflows/sync_crowdin.yml new file mode 100644 index 000000000..e0d0912b7 --- /dev/null +++ b/.github/workflows/sync_crowdin.yml @@ -0,0 +1,39 @@ +name: Sync Crowdin + +on: + workflow_dispatch: + schedule: + - cron: 0 * 1 * * + push: + paths: + - /src/main/resources/addresources/values/strings.xml + +jobs: + sync: + name: Sync translations + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Sync translations + uses: crowdin/github-action@v1 + with: + config: crowdin.yml + upload_sources: true + upload_translations: false + download_translations: true + localization_branch_name: feat/translations + create_pull_request: true + pull_request_title: "chore: Sync translations" + pull_request_body: "Sync translations from [crowdin.com/project/revanced](https://crowdin.com/project/revanced)" + pull_request_base_branch_name: "dev" + commit_message: "chore: Sync translations" + github_user_name: revanced-bot + github_user_email: github@revanced.app + env: + GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }} + CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} + CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index edf24bbed..79e017b34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,151 @@ +# [4.5.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.4.0...v4.5.0-dev.1) (2024-03-29) + + +### Features + +* **YouTube - Alternative thumbnails:** Selectively enable for home / subscription / search ([#2926](https://github.com/ReVanced/revanced-patches/issues/2926)) ([8549e1b](https://github.com/ReVanced/revanced-patches/commit/8549e1ba58ad1e1608f5e3ceacd31eeb94578949)) + +# [4.4.0](https://github.com/ReVanced/revanced-patches/compare/v4.3.0...v4.4.0) (2024-03-27) + + +### Bug Fixes + +* **TikTok:** Hook application context earlier to prevent crash ([#2893](https://github.com/ReVanced/revanced-patches/issues/2893)) ([395ccda](https://github.com/ReVanced/revanced-patches/commit/395ccda7b9218c522c7ca0f99f75a12036d3e3f3)) +* **YouTube - Client spoof:** Spoof all user agents ([44a8a13](https://github.com/ReVanced/revanced-patches/commit/44a8a1399897caaff3ff45db8549ddedb2f01b68)) +* **YouTube - Downloads:** Use new task context ([#2841](https://github.com/ReVanced/revanced-patches/issues/2841)) ([6d88cb4](https://github.com/ReVanced/revanced-patches/commit/6d88cb49ec739700866290babcba5fb3032dbced)) +* **YouTube - Hide ads:** Prevent app crash if hiding fullscreen ads is not possible ([#2910](https://github.com/ReVanced/revanced-patches/issues/2910)) ([9f50470](https://github.com/ReVanced/revanced-patches/commit/9f50470bf6582fe2f20a903a97bf66c41f296fb2)) +* **YouTube Music:** Fix compatibility with latest versions ([#2924](https://github.com/ReVanced/revanced-patches/issues/2924)) ([8378c84](https://github.com/ReVanced/revanced-patches/commit/8378c8481634a63a5568480475757e64b7ec466e)) +* **YouTube:** Fix video playback by switching to ReVanced GmsCore vendor ([#2907](https://github.com/ReVanced/revanced-patches/issues/2907)) ([33ea122](https://github.com/ReVanced/revanced-patches/commit/33ea12228c2ae5dcadf3e7c7016d4bf6006d899a)) +* **YouTube:** Move setting to correct screen ([a16eda8](https://github.com/ReVanced/revanced-patches/commit/a16eda864515612d3a6b846082844df15eb49f56)) + + +### Features + +* **Instagram - Hide timeline ads:** Make compatible with latest versions ([a212f29](https://github.com/ReVanced/revanced-patches/commit/a212f29bd33bb5e10f024e058d26e20ee926190b)) +* **Mi Fitness:** Add `Force English locale` and `Fix login` patch ([#2734](https://github.com/ReVanced/revanced-patches/issues/2734)) ([7a25791](https://github.com/ReVanced/revanced-patches/commit/7a25791d53530b1236896b2c3d6275ee7556e8b7)) +* **Sync for Lemmy:** Add `Disable ads` patch ([#2872](https://github.com/ReVanced/revanced-patches/issues/2872)) ([0785819](https://github.com/ReVanced/revanced-patches/commit/0785819dd5ad487c778b5baf09004cdab3687184)) +* **YouTube - Downloads:** Use external downloader when selecting 'Download' in home feed flyout menu ([#2881](https://github.com/ReVanced/revanced-patches/issues/2881)) ([10afc8c](https://github.com/ReVanced/revanced-patches/commit/10afc8cc71ff29fea4937fb12fd3d1edf9c581f5)) +* **YouTube - External downloader:** Add ability to use in-app download button ([d900011](https://github.com/ReVanced/revanced-patches/commit/d9000113a905c14f8409aa75008f1ef6a1aecd0c)) +* **YouTube - Hide layout components:** Filter home/search results by keywords ([#2853](https://github.com/ReVanced/revanced-patches/issues/2853)) ([5916204](https://github.com/ReVanced/revanced-patches/commit/59162042b0a68edf7f94a3c21f838dada3c3f9c3)) +* **YouTube - Hide Shorts components:** Hide like and dislike buttons ([2df0892](https://github.com/ReVanced/revanced-patches/commit/2df0892682406e67283c4aeaacebf8f222029833)) +* **YouTube - Hide Shorts components:** Hide sound metadata label ([ea7d1e0](https://github.com/ReVanced/revanced-patches/commit/ea7d1e0d08cc245117ffe8ad0df3c31c5e87f739)) +* **YouTube - Hide Shorts components:** Hide title and full video link label ([e7b64e1](https://github.com/ReVanced/revanced-patches/commit/e7b64e154e7fb8edd0037f5e171f4aa3ed9017f8)) +* **YouTube - Hide Shorts components:** Selectively hide Shorts for home / subscription / search ([#2925](https://github.com/ReVanced/revanced-patches/issues/2925)) ([497c067](https://github.com/ReVanced/revanced-patches/commit/497c067e80e560eb125f5fc30eef9763929b4ee4)) +* **YouTube :** Remove `HDR auto brightness` patch ([#2863](https://github.com/ReVanced/revanced-patches/issues/2863)) ([b4c7bf4](https://github.com/ReVanced/revanced-patches/commit/b4c7bf48084184e5f031f7f5139a9a29341d8ebf)) +* **YouTube Vanced:** Remove `Hide ads` patch ([87887e4](https://github.com/ReVanced/revanced-patches/commit/87887e4163dd9e242209f4d0fefb415f9bc7ca75)) +* **YouTube:** Support version `19.05`, `19.06`, `19.07`, `19.08` and `19.09` ([#2862](https://github.com/ReVanced/revanced-patches/issues/2862)) ([f044dde](https://github.com/ReVanced/revanced-patches/commit/f044dde054861ff16846a6be6287f86fa3afb3d8)) + +# [4.4.0-dev.15](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.14...v4.4.0-dev.15) (2024-03-27) + + +### Bug Fixes + +* **YouTube Music:** Fix compatibility with latest versions ([#2924](https://github.com/ReVanced/revanced-patches/issues/2924)) ([8378c84](https://github.com/ReVanced/revanced-patches/commit/8378c8481634a63a5568480475757e64b7ec466e)) + + +### Features + +* **YouTube - Hide Shorts components:** Selectively hide Shorts for home / subscription / search ([#2925](https://github.com/ReVanced/revanced-patches/issues/2925)) ([497c067](https://github.com/ReVanced/revanced-patches/commit/497c067e80e560eb125f5fc30eef9763929b4ee4)) + +# [4.4.0-dev.14](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.13...v4.4.0-dev.14) (2024-03-27) + + +### Features + +* **YouTube - Hide layout components:** Filter home/search results by keywords ([#2853](https://github.com/ReVanced/revanced-patches/issues/2853)) ([5916204](https://github.com/ReVanced/revanced-patches/commit/59162042b0a68edf7f94a3c21f838dada3c3f9c3)) + +# [4.4.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.12...v4.4.0-dev.13) (2024-03-26) + + +### Bug Fixes + +* **YouTube:** Move setting to correct screen ([a16eda8](https://github.com/ReVanced/revanced-patches/commit/a16eda864515612d3a6b846082844df15eb49f56)) + + +### Features + +* **YouTube - Hide Shorts components:** Hide like and dislike buttons ([2df0892](https://github.com/ReVanced/revanced-patches/commit/2df0892682406e67283c4aeaacebf8f222029833)) +* **YouTube - Hide Shorts components:** Hide sound metadata label ([ea7d1e0](https://github.com/ReVanced/revanced-patches/commit/ea7d1e0d08cc245117ffe8ad0df3c31c5e87f739)) +* **YouTube - Hide Shorts components:** Hide title and full video link label ([e7b64e1](https://github.com/ReVanced/revanced-patches/commit/e7b64e154e7fb8edd0037f5e171f4aa3ed9017f8)) + +# [4.4.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.11...v4.4.0-dev.12) (2024-03-25) + + +### Bug Fixes + +* **YouTube:** Fix video playback by switching to ReVanced GmsCore vendor ([#2907](https://github.com/ReVanced/revanced-patches/issues/2907)) ([33ea122](https://github.com/ReVanced/revanced-patches/commit/33ea12228c2ae5dcadf3e7c7016d4bf6006d899a)) + +# [4.4.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.10...v4.4.0-dev.11) (2024-03-25) + + +### Features + +* **Mi Fitness:** Add `Force English locale` and `Fix login` patch ([#2734](https://github.com/ReVanced/revanced-patches/issues/2734)) ([7a25791](https://github.com/ReVanced/revanced-patches/commit/7a25791d53530b1236896b2c3d6275ee7556e8b7)) +* **Sync for Lemmy:** Add `Disable ads` patch ([#2872](https://github.com/ReVanced/revanced-patches/issues/2872)) ([0785819](https://github.com/ReVanced/revanced-patches/commit/0785819dd5ad487c778b5baf09004cdab3687184)) + +# [4.4.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.9...v4.4.0-dev.10) (2024-03-25) + + +### Bug Fixes + +* **YouTube - Hide ads:** Prevent app crash if hiding fullscreen ads is not possible ([#2910](https://github.com/ReVanced/revanced-patches/issues/2910)) ([9f50470](https://github.com/ReVanced/revanced-patches/commit/9f50470bf6582fe2f20a903a97bf66c41f296fb2)) + +# [4.4.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.8...v4.4.0-dev.9) (2024-03-18) + + +### Bug Fixes + +* **TikTok:** Hook application context earlier to prevent crash ([#2893](https://github.com/ReVanced/revanced-patches/issues/2893)) ([395ccda](https://github.com/ReVanced/revanced-patches/commit/395ccda7b9218c522c7ca0f99f75a12036d3e3f3)) + +# [4.4.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.7...v4.4.0-dev.8) (2024-03-15) + + +### Features + +* **YouTube - Downloads:** Use external downloader when selecting 'Download' in home feed flyout menu ([#2881](https://github.com/ReVanced/revanced-patches/issues/2881)) ([10afc8c](https://github.com/ReVanced/revanced-patches/commit/10afc8cc71ff29fea4937fb12fd3d1edf9c581f5)) + +# [4.4.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.6...v4.4.0-dev.7) (2024-03-14) + + +### Bug Fixes + +* **YouTube - Client spoof:** Spoof all user agents ([44a8a13](https://github.com/ReVanced/revanced-patches/commit/44a8a1399897caaff3ff45db8549ddedb2f01b68)) + +# [4.4.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.5...v4.4.0-dev.6) (2024-03-12) + + +### Features + +* **Instagram - Hide timeline ads:** Make compatible with latest versions ([a212f29](https://github.com/ReVanced/revanced-patches/commit/a212f29bd33bb5e10f024e058d26e20ee926190b)) + +# [4.4.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.4...v4.4.0-dev.5) (2024-03-11) + + +### Features + +* **YouTube:** Support version `19.05`, `19.06`, `19.07`, `19.08` and `19.09` ([#2862](https://github.com/ReVanced/revanced-patches/issues/2862)) ([f044dde](https://github.com/ReVanced/revanced-patches/commit/f044dde054861ff16846a6be6287f86fa3afb3d8)) + +# [4.4.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.3...v4.4.0-dev.4) (2024-03-11) + + +### Features + +* **YouTube :** Remove `HDR auto brightness` patch ([#2863](https://github.com/ReVanced/revanced-patches/issues/2863)) ([b4c7bf4](https://github.com/ReVanced/revanced-patches/commit/b4c7bf48084184e5f031f7f5139a9a29341d8ebf)) + +# [4.4.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.2...v4.4.0-dev.3) (2024-03-08) + + +### Bug Fixes + +* **YouTube - Downloads:** Use new task context ([#2841](https://github.com/ReVanced/revanced-patches/issues/2841)) ([6d88cb4](https://github.com/ReVanced/revanced-patches/commit/6d88cb49ec739700866290babcba5fb3032dbced)) + +# [4.4.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.4.0-dev.1...v4.4.0-dev.2) (2024-03-04) + + +### Features + +* **YouTube - External downloader:** Add ability to use in-app download button ([d900011](https://github.com/ReVanced/revanced-patches/commit/d9000113a905c14f8409aa75008f1ef6a1aecd0c)) + # [4.4.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.3.0...v4.4.0-dev.1) (2024-03-04) diff --git a/api/revanced-patches.api b/api/revanced-patches.api index dd2656729..274be1988 100644 --- a/api/revanced-patches.api +++ b/api/revanced-patches.api @@ -284,12 +284,30 @@ public final class app/revanced/patches/messenger/inputfield/patch/DisableTyping public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } +public final class app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch; + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + +public final class app/revanced/patches/mifitness/misc/login/FixLoginPatch : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/mifitness/misc/login/FixLoginPatch; + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + public final class app/revanced/patches/moneymanager/UnlockProPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/moneymanager/UnlockProPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } +public final class app/revanced/patches/music/ad/video/HideMusicVideoAds : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/music/ad/video/HideMusicVideoAds; + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + public final class app/revanced/patches/music/ad/video/MusicVideoAdsPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/music/ad/video/MusicVideoAdsPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V @@ -302,6 +320,12 @@ public final class app/revanced/patches/music/audio/codecs/CodecsUnlockPatch : a public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } +public final class app/revanced/patches/music/audio/exclusiveaudio/EnableExclusiveAudioPlayback : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/music/audio/exclusiveaudio/EnableExclusiveAudioPlayback; + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + public final class app/revanced/patches/music/audio/exclusiveaudio/ExclusiveAudioPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/music/audio/exclusiveaudio/ExclusiveAudioPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V @@ -320,12 +344,24 @@ public final class app/revanced/patches/music/interaction/permanentshuffle/Perma public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } +public final class app/revanced/patches/music/interaction/permanentshuffle/PermanentShuffleTogglePatch : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/music/interaction/permanentshuffle/PermanentShuffleTogglePatch; + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + public final class app/revanced/patches/music/layout/compactheader/CompactHeaderPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/music/layout/compactheader/CompactHeaderPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } +public final class app/revanced/patches/music/layout/compactheader/HideCategoryBar : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/music/layout/compactheader/HideCategoryBar; + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + public final class app/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V @@ -481,6 +517,13 @@ public final class app/revanced/patches/reddit/customclients/Constants { public static final field OAUTH_USER_AGENT Ljava/lang/String; } +public abstract class app/revanced/patches/reddit/customclients/ads/BaseDisableAdsPatch : app/revanced/patcher/patch/BytecodePatch { + public fun (Ljava/util/Set;Ljava/util/Set;)V + public synthetic fun (Ljava/util/Set;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + public final class app/revanced/patches/reddit/customclients/baconreader/api/SpoofClientPatch : app/revanced/patches/reddit/customclients/BaseSpoofClientPatch { public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/baconreader/api/SpoofClientPatch; public fun patchClientId (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V @@ -536,10 +579,12 @@ public final class app/revanced/patches/reddit/customclients/slide/api/SpoofClie public fun patchClientId (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V } -public final class app/revanced/patches/reddit/customclients/syncforreddit/ads/DisableAdsPatch : app/revanced/patcher/patch/BytecodePatch { +public final class app/revanced/patches/reddit/customclients/syncforlemmy/ads/DisableAdsPatch : app/revanced/patches/reddit/customclients/ads/BaseDisableAdsPatch { + public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforlemmy/ads/DisableAdsPatch; +} + +public final class app/revanced/patches/reddit/customclients/syncforreddit/ads/DisableAdsPatch : app/revanced/patches/reddit/customclients/ads/BaseDisableAdsPatch { public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/ads/DisableAdsPatch; - public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V - public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } public final class app/revanced/patches/reddit/customclients/syncforreddit/annoyances/startup/DisableSyncForLemmyBottomSheetPatch : app/revanced/patcher/patch/BytecodePatch { @@ -615,6 +660,7 @@ public abstract class app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportRes public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V protected final fun getGmsCoreVendor ()Ljava/lang/String; + protected final fun getGmsCoreVendorGroupId ()Ljava/lang/String; } public abstract class app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch : app/revanced/patcher/patch/BytecodePatch { @@ -628,9 +674,19 @@ public abstract class app/revanced/patches/shared/misc/integrations/BaseIntegrat public fun ()V public fun (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)V public synthetic fun (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun invoke (Ljava/lang/String;)V } +public abstract interface class app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch$IntegrationsFingerprint$IHookInsertIndexResolver : kotlin/jvm/functions/Function1 { + public abstract fun invoke (Lcom/android/tools/smali/dexlib2/iface/Method;)Ljava/lang/Integer; +} + +public final class app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch$IntegrationsFingerprint$IHookInsertIndexResolver$DefaultImpls { + public static fun invoke (Lapp/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch$IntegrationsFingerprint$IHookInsertIndexResolver;Lcom/android/tools/smali/dexlib2/iface/Method;)Ljava/lang/Integer; +} + public abstract interface class app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch$IntegrationsFingerprint$IRegisterResolver : kotlin/jvm/functions/Function1 { public abstract fun invoke (Lcom/android/tools/smali/dexlib2/iface/Method;)Ljava/lang/Integer; } @@ -894,8 +950,8 @@ public final class app/revanced/patches/strava/upselling/DisableSubscriptionSugg public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } -public final class app/revanced/patches/ticktick/misc/themeunlock/UnlockThemesPatch : app/revanced/patcher/patch/BytecodePatch { - public static final field INSTANCE Lapp/revanced/patches/ticktick/misc/themeunlock/UnlockThemesPatch; +public final class app/revanced/patches/ticktick/misc/themeunlock/UnlockProPatch : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/ticktick/misc/themeunlock/UnlockProPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } @@ -1194,8 +1250,8 @@ public final class app/revanced/patches/youtube/interaction/dialog/RemoveViewerD public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } -public final class app/revanced/patches/youtube/interaction/downloads/ExternalDownloadsBytecodePatch : app/revanced/patcher/patch/BytecodePatch { - public static final field INSTANCE Lapp/revanced/patches/youtube/interaction/downloads/ExternalDownloadsBytecodePatch; +public final class app/revanced/patches/youtube/interaction/downloads/DownloadsPatch : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/youtube/interaction/downloads/DownloadsPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } @@ -1514,10 +1570,12 @@ public final class app/revanced/patches/youtube/misc/dimensions/spoof/SpoofDevic public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } -public final class app/revanced/patches/youtube/misc/fix/playback/ClientSpoofPatch : app/revanced/patcher/patch/BytecodePatch { +public final class app/revanced/patches/youtube/misc/fix/playback/ClientSpoofPatch : app/revanced/patches/all/misc/transformation/BaseTransformInstructionsPatch { public static final field INSTANCE Lapp/revanced/patches/youtube/misc/fix/playback/ClientSpoofPatch; - public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V - public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V + public synthetic fun filterMap (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;I)Ljava/lang/Object; + public fun filterMap (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;I)Lkotlin/Triple; + public synthetic fun transform (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/Object;)V + public fun transform (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Lkotlin/Triple;)V } public final class app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch : app/revanced/patcher/patch/BytecodePatch { @@ -1575,6 +1633,13 @@ public final class app/revanced/patches/youtube/misc/minimizedplayback/Minimized public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } +public final class app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch; + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V + public final fun getHookNavigationButtonCreated ()Lkotlin/jvm/functions/Function1; +} + public final class app/revanced/patches/youtube/misc/playercontrols/BottomControlsResourcePatch : app/revanced/patcher/patch/ResourcePatch, java/io/Closeable { public static final field INSTANCE Lapp/revanced/patches/youtube/misc/playercontrols/BottomControlsResourcePatch; public final fun addControls (Ljava/lang/String;)V @@ -1748,6 +1813,7 @@ public final class app/revanced/util/BytecodeUtilsKt { public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)I public static final fun indexOfFirstWideLiteralInstructionValue (Lcom/android/tools/smali/dexlib2/iface/Method;J)I public static final fun injectHideViewCall (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;IILjava/lang/String;Ljava/lang/String;)V + public static final fun resultOrThrow (Lapp/revanced/patcher/fingerprint/MethodFingerprint;)Lapp/revanced/patcher/fingerprint/MethodFingerprintResult; public static final fun returnEarly (Ljava/util/List;Z)V public static synthetic fun returnEarly$default (Ljava/util/List;ZILjava/lang/Object;)V public static final fun transformMethods (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lkotlin/jvm/functions/Function1;)V diff --git a/build.gradle.kts b/build.gradle.kts index 5942f58c6..58308fbf4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,4 +1,5 @@ import org.gradle.kotlin.dsl.support.listFilesOrdered +import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { alias(libs.plugins.kotlin) @@ -33,7 +34,13 @@ dependencies { } kotlin { - jvmToolchain(11) + compilerOptions { + jvmTarget.set(JvmTarget.JVM_11) + } +} + +java { + targetCompatibility = JavaVersion.VERSION_11 } tasks { diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 000000000..4ac3cb98b --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,8 @@ +project_id_env: "CROWDIN_PROJECT_ID" +api_token_env: "CROWDIN_PERSONAL_TOKEN" + +preserve_hierarchy: false +files: + - source: src/main/resources/addresources/values/strings.xml + translation: src/main/resources/addresources/values-%android_code%/strings.xml + skip_untranslated_strings: true diff --git a/gradle.properties b/gradle.properties index c81183862..f13505f4e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true kotlin.code.style = official -version = 4.4.0-dev.1 +version = 4.5.0-dev.1 diff --git a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/HideTimelineAdsPatch.kt b/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/HideTimelineAdsPatch.kt index 4a154ce72..2cb98620c 100644 --- a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/HideTimelineAdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/HideTimelineAdsPatch.kt @@ -3,102 +3,61 @@ package app.revanced.patches.instagram.patches.ads.timeline import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.smali.ExternalLabel -import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.MediaFingerprint +import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.IsAdCheckOneFingerprint +import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.IsAdCheckTwoFingerprint import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ShowAdFingerprint -import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.GenericMediaAdFingerprint -import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.MediaAdFingerprint -import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.PaidPartnershipAdFingerprint -import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.ShoppingAdFingerprint import app.revanced.util.exception import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @Patch( name = "Hide timeline ads", - description = "Removes ads from the timeline.", - compatiblePackages = [CompatiblePackage("com.instagram.android", ["275.0.0.27.98"])], + compatiblePackages = [CompatiblePackage("com.instagram.android")], ) @Suppress("unused") object HideTimelineAdsPatch : BytecodePatch( setOf( ShowAdFingerprint, - MediaFingerprint, - // Unlike the other ads this one is resolved from all classes. - PaidPartnershipAdFingerprint, + IsAdCheckOneFingerprint, + IsAdCheckTwoFingerprint, ), ) { override fun execute(context: BytecodeContext) { - // region Resolve required methods to check for ads. + // The exact function of the following methods is unknown. + // They are used to check if a post is an ad. + val isAdCheckOneMethod = IsAdCheckOneFingerprint.result?.method ?: throw IsAdCheckOneFingerprint.exception + val isAdCheckTwoMethod = IsAdCheckTwoFingerprint.result?.method ?: throw IsAdCheckTwoFingerprint.exception - ShowAdFingerprint.result ?: throw ShowAdFingerprint.exception + ShowAdFingerprint.result?.let { + it.mutableMethod.apply { + // The register that holds the post object. + val postRegister = getInstruction(1).registerC - PaidPartnershipAdFingerprint.result ?: throw PaidPartnershipAdFingerprint.exception + // At this index the check for an ad can be performed. + val checkIndex = it.scanResult.patternScanResult!!.endIndex - MediaFingerprint.result?.let { - GenericMediaAdFingerprint.resolve(context, it.classDef) - ShoppingAdFingerprint.resolve(context, it.classDef) - - return@let - } ?: throw MediaFingerprint.exception - - // endregion - - ShowAdFingerprint.result!!.apply { - // region Create instructions. - - val scanStart = scanResult.patternScanResult!!.startIndex - val jumpIndex = scanStart - 1 - - val mediaInstanceRegister = mutableMethod.getInstruction(scanStart).registerC - val freeRegister = mutableMethod.getInstruction(jumpIndex).registerA - - val returnFalseLabel = "an_ad" - - val checkForAdInstructions = - listOf(GenericMediaAdFingerprint, PaidPartnershipAdFingerprint, ShoppingAdFingerprint) - .map(MediaAdFingerprint::toString) - .joinToString("\n") { - """ - invoke-virtual {v$mediaInstanceRegister}, $it - move-result v$freeRegister - if-nez v$freeRegister, :$returnFalseLabel - """.trimIndent() - }.let { "$it\nconst/4 v0, 0x1\nreturn v0" } - - // endregion - - // region Patch. - - val insertIndex = scanStart + 3 - - mutableMethod.addInstructionsWithLabels( - insertIndex, - checkForAdInstructions, - ExternalLabel( - returnFalseLabel, - // return false = ad - mutableMethod.getInstruction(mutableMethod.implementation!!.instructions.size - 2), - ), - ) - - // endregion - - // region Jump to checks for ads from previous patch. - - mutableMethod.apply { + // If either check returns true, the post is an ad and is hidden by returning false. addInstructionsWithLabels( - jumpIndex + 1, - "if-nez v$freeRegister, :start_check", - ExternalLabel("start_check", getInstruction(insertIndex)), + checkIndex, + """ + invoke-virtual { v$postRegister }, $isAdCheckOneMethod + move-result v0 + if-nez v0, :hide_ad + + invoke-static { v$postRegister }, $isAdCheckTwoMethod + move-result v0 + if-eqz v0, :not_an_ad + + :hide_ad + const/4 v0, 0x0 # Returning false to hide the ad. + return v0 + """, + ExternalLabel("not_an_ad", getInstruction(checkIndex)), ) - }.removeInstruction(jumpIndex) - - // endregion - } + } + } ?: throw ShowAdFingerprint.exception } } diff --git a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/IsAdCheckOneFingerprint.kt b/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/IsAdCheckOneFingerprint.kt new file mode 100644 index 000000000..58380feba --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/IsAdCheckOneFingerprint.kt @@ -0,0 +1,18 @@ +package app.revanced.patches.instagram.patches.ads.timeline.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +internal object IsAdCheckOneFingerprint : MethodFingerprint( + returnType = "Z", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + parameters = listOf(), + opcodes = listOf( + Opcode.XOR_INT_LIT8, + Opcode.IF_NE, + Opcode.RETURN, + Opcode.INVOKE_VIRTUAL, + ), +) diff --git a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/GenericMediaAdFingerprint.kt b/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/IsAdCheckTwoFingerprint.kt similarity index 52% rename from src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/GenericMediaAdFingerprint.kt rename to src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/IsAdCheckTwoFingerprint.kt index 6e6caabd2..aa826abf9 100644 --- a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/GenericMediaAdFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/IsAdCheckTwoFingerprint.kt @@ -1,8 +1,14 @@ -package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads +package app.revanced.patches.instagram.patches.ads.timeline.fingerprints +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal object GenericMediaAdFingerprint : MediaAdFingerprint( +internal object IsAdCheckTwoFingerprint : MethodFingerprint( + returnType = "Z", + accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, + parameters = listOf("L"), opcodes = listOf( Opcode.INVOKE_INTERFACE, Opcode.MOVE_RESULT_OBJECT, @@ -13,6 +19,4 @@ internal object GenericMediaAdFingerprint : MediaAdFingerprint( Opcode.CONST_4, Opcode.RETURN, ), -) { - override fun toString() = result!!.method.toString() -} +) diff --git a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/MediaFingerprint.kt b/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/MediaFingerprint.kt deleted file mode 100644 index e70921639..000000000 --- a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/MediaFingerprint.kt +++ /dev/null @@ -1,7 +0,0 @@ -package app.revanced.patches.instagram.patches.ads.timeline.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint - -internal object MediaFingerprint : MethodFingerprint( - strings = listOf("force_overlay", "Media#updateFields", "live_reels_metadata"), -) diff --git a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ShowAdFingerprint.kt b/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ShowAdFingerprint.kt index 53ab5ee97..70eda9abd 100644 --- a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ShowAdFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ShowAdFingerprint.kt @@ -10,16 +10,12 @@ internal object ShowAdFingerprint : MethodFingerprint( AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.FINAL, listOf("L", "L", "Z", "Z"), opcodes = listOf( + Opcode.SGET_OBJECT, + Opcode.IF_NE, + Opcode.IF_NEZ, Opcode.INVOKE_STATIC, Opcode.MOVE_RESULT, Opcode.IF_NEZ, Opcode.RETURN, - Opcode.CONST_4, - Opcode.GOTO, - Opcode.CONST_4, - Opcode.GOTO, - Opcode.CONST_4, - Opcode.GOTO, - Opcode.CONST_4, ), ) 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 deleted file mode 100644 index 142971619..000000000 --- a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/MediaAdFingerprint.kt +++ /dev/null @@ -1,24 +0,0 @@ -package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.ClassDef -import com.android.tools.smali.dexlib2.iface.Method - -internal abstract class MediaAdFingerprint( - returnType: String? = "Z", - accessFlags: Int? = AccessFlags.PUBLIC or AccessFlags.FINAL, - parameters: Iterable? = listOf(), - opcodes: Iterable?, - customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null, -) : MethodFingerprint( - returnType, - accessFlags, - parameters, - opcodes, - customFingerprint = customFingerprint, -) { - abstract override fun toString(): String -} 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 deleted file mode 100644 index 082ab54b5..000000000 --- a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/PaidPartnershipAdFingerprint.kt +++ /dev/null @@ -1,29 +0,0 @@ -package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads - -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction -import com.android.tools.smali.dexlib2.iface.reference.MethodReference - -internal object PaidPartnershipAdFingerprint : MediaAdFingerprint( - "V", - null, - listOf("L", "L"), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IPUT_BOOLEAN, - Opcode.IPUT_BOOLEAN, - ), - customFingerprint = { methodDef, _ -> - methodDef.definingClass.endsWith("ClipsEditMetadataController;") - }, -) { - override fun toString() = result!!.let { - val adCheckIndex = it.scanResult.patternScanResult!!.startIndex - val adCheckInstruction = it.method.implementation!!.instructions.elementAt(adCheckIndex) - - val adCheckMethod = (adCheckInstruction as ReferenceInstruction).reference as MethodReference - - adCheckMethod.toString() - } -} diff --git a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/ShoppingAdFingerprint.kt b/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/ShoppingAdFingerprint.kt deleted file mode 100644 index b1f9e4087..000000000 --- a/src/main/kotlin/app/revanced/patches/instagram/patches/ads/timeline/fingerprints/ads/ShoppingAdFingerprint.kt +++ /dev/null @@ -1,21 +0,0 @@ -package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads - -import com.android.tools.smali.dexlib2.Opcode - -internal object ShoppingAdFingerprint : MediaAdFingerprint( - opcodes = listOf( - Opcode.IF_EQZ, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IF_EQZ, - Opcode.IGET_OBJECT, - Opcode.IF_EQZ, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.XOR_INT_LIT8, - Opcode.IF_EQZ, - ), -) { - override fun toString() = result!!.method.toString() -} diff --git a/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch.kt b/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch.kt new file mode 100644 index 000000000..c71b0c626 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch.kt @@ -0,0 +1,39 @@ +package app.revanced.patches.mifitness.misc.locale + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.annotation.CompatiblePackage +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patches.mifitness.misc.locale.fingerprints.SyncBluetoothLanguageFingerprint +import app.revanced.patches.mifitness.misc.login.FixLoginPatch +import app.revanced.util.exception +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction + +@Patch( + name = "Force English locale", + description = "Forces wearable devices to use the English locale.", + compatiblePackages = [CompatiblePackage("com.xiaomi.wearable")], + dependencies = [FixLoginPatch::class], +) +@Suppress("unused") +object ForceEnglishLocalePatch : BytecodePatch( + setOf(SyncBluetoothLanguageFingerprint), +) { + override fun execute(context: BytecodeContext) { + SyncBluetoothLanguageFingerprint.result?.let { + val resolvePhoneLocaleInstruction = it.scanResult.patternScanResult!!.startIndex + + it.mutableMethod.apply { + val registerIndexToUpdate = + getInstruction(resolvePhoneLocaleInstruction).registerA + + replaceInstruction( + resolvePhoneLocaleInstruction, + "const-string v$registerIndexToUpdate, \"en_gb\"", + ) + } + } ?: throw SyncBluetoothLanguageFingerprint.exception + } +} diff --git a/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/fingerprints/SyncBluetoothLanguageFingerprint.kt b/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/fingerprints/SyncBluetoothLanguageFingerprint.kt new file mode 100644 index 000000000..95c9a43f0 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/fingerprints/SyncBluetoothLanguageFingerprint.kt @@ -0,0 +1,12 @@ +package app.revanced.patches.mifitness.misc.locale.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.Opcode + +internal object SyncBluetoothLanguageFingerprint : MethodFingerprint( + customFingerprint = { methodDef, _ -> + methodDef.definingClass == "Lcom/xiaomi/fitness/devicesettings/DeviceSettingsSyncer;" && + methodDef.name == "syncBluetoothLanguage" + }, + opcodes = listOf(Opcode.MOVE_RESULT_OBJECT), +) diff --git a/src/main/kotlin/app/revanced/patches/mifitness/misc/login/FixLoginPatch.kt b/src/main/kotlin/app/revanced/patches/mifitness/misc/login/FixLoginPatch.kt new file mode 100644 index 000000000..cf67c893d --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/mifitness/misc/login/FixLoginPatch.kt @@ -0,0 +1,35 @@ +package app.revanced.patches.mifitness.misc.login + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.annotation.CompatiblePackage +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patches.mifitness.misc.login.fingerprints.XiaomiAccountManagerConstructorFingerprint +import app.revanced.util.exception +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction + +@Patch( + name = "Fix login", + description = "Fixes login for uncertified Mi Fitness app", + compatiblePackages = [CompatiblePackage("com.xiaomi.wearable")], +) +@Suppress("unused") +object FixLoginPatch : BytecodePatch( + setOf(XiaomiAccountManagerConstructorFingerprint), +) { + override fun execute(context: BytecodeContext) { + XiaomiAccountManagerConstructorFingerprint.result?.let { + it.mutableMethod.apply { + val isCertifiedIndex = it.scanResult.patternScanResult!!.startIndex + val isCertifiedRegister = getInstruction(isCertifiedIndex).registerA + + addInstruction( + isCertifiedIndex, + "const/4 p$isCertifiedRegister, 0x0", + ) + } + } ?: throw XiaomiAccountManagerConstructorFingerprint.exception + } +} diff --git a/src/main/kotlin/app/revanced/patches/mifitness/misc/login/fingerprints/XiaomiAccountManagerConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/mifitness/misc/login/fingerprints/XiaomiAccountManagerConstructorFingerprint.kt new file mode 100644 index 000000000..e5d06acef --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/mifitness/misc/login/fingerprints/XiaomiAccountManagerConstructorFingerprint.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.mifitness.misc.login.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +internal object XiaomiAccountManagerConstructorFingerprint : MethodFingerprint( + accessFlags = AccessFlags.PRIVATE or AccessFlags.CONSTRUCTOR, + customFingerprint = { methodDef, _ -> + methodDef.definingClass == "Lcom/xiaomi/passport/accountmanager/XiaomiAccountManager;" + }, + opcodes = listOf(Opcode.IF_NEZ), +) diff --git a/src/main/kotlin/app/revanced/patches/music/ad/video/HideMusicVideoAds.kt b/src/main/kotlin/app/revanced/patches/music/ad/video/HideMusicVideoAds.kt new file mode 100644 index 000000000..6f533c2f9 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/ad/video/HideMusicVideoAds.kt @@ -0,0 +1,37 @@ +package app.revanced.patches.music.ad.video + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.annotation.CompatiblePackage +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod +import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsParentFingerprint +import app.revanced.util.exception + +@Patch( + name = "Hide music video ads", + compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], +) +@Suppress("unused") +object HideMusicVideoAds : BytecodePatch( + setOf(ShowMusicVideoAdsParentFingerprint), +) { + override fun execute(context: BytecodeContext) { + ShowMusicVideoAdsParentFingerprint.result?.let { + val showMusicVideoAdsMethod = context + .toMethodWalker(it.mutableMethod) + .nextMethod(it.scanResult.patternScanResult!!.startIndex + 1, true).getMethod() as MutableMethod + + showMusicVideoAdsMethod.addInstruction(0, "const/4 p1, 0x0") + } ?: throw ShowMusicVideoAdsParentFingerprint.exception + } +} + +@Deprecated("This patch class has been renamed to HideMusicVideoAds.") +object MusicVideoAdsPatch : BytecodePatch( + dependencies = setOf(HideMusicVideoAds::class), +) { + override fun execute(context: BytecodeContext) { + } +} diff --git a/src/main/kotlin/app/revanced/patches/music/ad/video/MusicVideoAdsPatch.kt b/src/main/kotlin/app/revanced/patches/music/ad/video/MusicVideoAdsPatch.kt deleted file mode 100644 index 2065fc229..000000000 --- a/src/main/kotlin/app/revanced/patches/music/ad/video/MusicVideoAdsPatch.kt +++ /dev/null @@ -1,32 +0,0 @@ -package app.revanced.patches.music.ad.video - -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.annotation.CompatiblePackage -import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsConstructorFingerprint -import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsFingerprint - -@Patch( - name = "Music video ads", - description = "Removes ads in the music player.", - compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], -) -@Suppress("unused") -object MusicVideoAdsPatch : BytecodePatch( - setOf(ShowMusicVideoAdsConstructorFingerprint), -) { - override fun execute(context: BytecodeContext) { - ShowMusicVideoAdsFingerprint.resolve(context, ShowMusicVideoAdsConstructorFingerprint.result!!.classDef) - - val result = ShowMusicVideoAdsFingerprint.result!! - - result.mutableMethod.addInstruction( - result.scanResult.patternScanResult!!.startIndex, - """ - const/4 p1, 0x0 - """, - ) - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsConstructorFingerprint.kt deleted file mode 100644 index 03e202fa9..000000000 --- a/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsConstructorFingerprint.kt +++ /dev/null @@ -1,30 +0,0 @@ -package app.revanced.patches.music.ad.video.fingerprints -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode - -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. -internal object ShowMusicVideoAdsConstructorFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, - listOf("L", "L", "L"), - listOf( - Opcode.INVOKE_DIRECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST_4, - Opcode.IPUT_BOOLEAN, - Opcode.RETURN_VOID, - ), -) diff --git a/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsFingerprint.kt deleted file mode 100644 index be5491bb1..000000000 --- a/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsFingerprint.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.revanced.patches.music.ad.video.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode - -internal object ShowMusicVideoAdsFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf("Z"), - listOf( - Opcode.IPUT_BOOLEAN, - Opcode.INVOKE_VIRTUAL, - Opcode.RETURN_VOID, - ), -) diff --git a/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsParentFingerprint.kt new file mode 100644 index 000000000..5996ee98d --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsParentFingerprint.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.music.ad.video.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.Opcode + +internal object ShowMusicVideoAdsParentFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.IGET_OBJECT, + ), + strings = listOf("maybeRegenerateCpnAndStatsClient called unexpectedly, but no error."), +) diff --git a/src/main/kotlin/app/revanced/patches/music/audio/codecs/CodecsUnlockPatch.kt b/src/main/kotlin/app/revanced/patches/music/audio/codecs/CodecsUnlockPatch.kt index a155113b4..0c1cbebc6 100644 --- a/src/main/kotlin/app/revanced/patches/music/audio/codecs/CodecsUnlockPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/audio/codecs/CodecsUnlockPatch.kt @@ -10,11 +10,10 @@ import app.revanced.patches.music.audio.codecs.fingerprints.CodecsLockFingerprin import com.android.tools.smali.dexlib2.Opcode @Patch( - name = "Codecs unlock", description = "Adds more audio codec options. The new audio codecs usually result in better audio quality.", compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], ) -@Suppress("unused") +@Deprecated("This patch is no longer needed as the feature is now enabled by default.") object CodecsUnlockPatch : BytecodePatch( setOf(CodecsLockFingerprint, AllCodecsReferenceFingerprint), ) { diff --git a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/ExclusiveAudioPatch.kt b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/EnableExclusiveAudioPlayback.kt similarity index 76% rename from src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/ExclusiveAudioPatch.kt rename to src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/EnableExclusiveAudioPlayback.kt index 5875a311e..79f3fc0f1 100644 --- a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/ExclusiveAudioPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/EnableExclusiveAudioPlayback.kt @@ -9,12 +9,12 @@ import app.revanced.patches.music.audio.exclusiveaudio.fingerprints.AllowExclusi import app.revanced.util.exception @Patch( - name = "Exclusive audio playback", + name = "Enable exclusive audio playback", description = "Enables the option to play audio without video.", compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], ) @Suppress("unused") -object ExclusiveAudioPatch : BytecodePatch( +object EnableExclusiveAudioPlayback : BytecodePatch( setOf(AllowExclusiveAudioPlaybackFingerprint), ) { override fun execute(context: BytecodeContext) { @@ -29,3 +29,8 @@ object ExclusiveAudioPatch : BytecodePatch( } ?: throw AllowExclusiveAudioPlaybackFingerprint.exception } } + +@Deprecated("This patch class has been renamed to EnableExclusiveAudioPlayback.") +object ExclusiveAudioPatch : BytecodePatch(emptySet()) { + override fun execute(context: BytecodeContext) = EnableExclusiveAudioPlayback.execute(context) +} diff --git a/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch.kt b/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch.kt index 3fc9b3fda..88dff320e 100644 --- a/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch.kt @@ -22,3 +22,11 @@ object PermanentShufflePatch : BytecodePatch(setOf(DisableShuffleFingerprint)) { ?: throw DisableShuffleFingerprint.exception } } + +@Deprecated("This patch class has been renamed to PermanentShufflePatch.") +object PermanentShuffleTogglePatch : BytecodePatch( + dependencies = setOf(PermanentShufflePatch::class), +) { + override fun execute(context: BytecodeContext) { + } +} diff --git a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/CompactHeaderPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/CompactHeaderPatch.kt deleted file mode 100644 index 459a62bef..000000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/CompactHeaderPatch.kt +++ /dev/null @@ -1,35 +0,0 @@ -package app.revanced.patches.music.layout.compactheader - -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.annotation.CompatiblePackage -import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.music.layout.compactheader.fingerprints.CompactHeaderConstructorFingerprint -import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction11x - -@Patch( - name = "Compact header", - description = "Hides the music category bar at the top of the homepage.", - compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], - use = false, -) -@Suppress("unused") -object CompactHeaderPatch : BytecodePatch( - setOf(CompactHeaderConstructorFingerprint), -) { - override fun execute(context: BytecodeContext) { - val result = CompactHeaderConstructorFingerprint.result!! - val method = result.mutableMethod - - val insertIndex = result.scanResult.patternScanResult!!.endIndex - val register = (method.implementation!!.instructions[insertIndex - 1] as BuilderInstruction11x).registerA - method.addInstructions( - insertIndex, - """ - const/16 v2, 0x8 - invoke-virtual {v$register, v2}, Landroid/view/View;->setVisibility(I)V - """, - ) - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/HideCategoryBar.kt b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/HideCategoryBar.kt new file mode 100644 index 000000000..0cc8e9493 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/HideCategoryBar.kt @@ -0,0 +1,47 @@ +package app.revanced.patches.music.layout.compactheader + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.annotation.CompatiblePackage +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patches.music.layout.compactheader.fingerprints.ConstructCategoryBarFingerprint +import app.revanced.util.exception +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction + +@Patch( + name = "Hide category bar", + description = "Hides the category bar at the top of the homepage.", + compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], + use = false, +) +@Suppress("unused") +object HideCategoryBar : BytecodePatch( + setOf(ConstructCategoryBarFingerprint), +) { + override fun execute(context: BytecodeContext) { + ConstructCategoryBarFingerprint.result?.let { + it.mutableMethod.apply { + val insertIndex = it.scanResult.patternScanResult!!.startIndex + val register = getInstruction(insertIndex - 1).registerA + + addInstructions( + insertIndex, + """ + const/16 v2, 0x8 + invoke-virtual {v$register, v2}, Landroid/view/View;->setVisibility(I)V + """, + ) + } + } ?: throw ConstructCategoryBarFingerprint.exception + } +} + +@Deprecated("This patch class has been renamed to HideCategoryBar.") +object CompactHeaderPatch : BytecodePatch( + dependencies = setOf(HideCategoryBar::class), +) { + override fun execute(context: BytecodeContext) { + } +} diff --git a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/fingerprints/CompactHeaderConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/fingerprints/ConstructCategoryBarFingerprint.kt similarity index 65% rename from src/main/kotlin/app/revanced/patches/music/layout/compactheader/fingerprints/CompactHeaderConstructorFingerprint.kt rename to src/main/kotlin/app/revanced/patches/music/layout/compactheader/fingerprints/ConstructCategoryBarFingerprint.kt index c6c3888a4..903222c55 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/fingerprints/CompactHeaderConstructorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/fingerprints/ConstructCategoryBarFingerprint.kt @@ -5,22 +5,19 @@ import app.revanced.patcher.fingerprint.MethodFingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal object CompactHeaderConstructorFingerprint : MethodFingerprint( +internal object ConstructCategoryBarFingerprint : MethodFingerprint( "V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, - listOf("L", "L", "L", "L", "L"), + listOf("Landroid/content/Context;", "L", "L", "L"), listOf( - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, Opcode.IPUT_OBJECT, Opcode.CONST, - Opcode.CONST_4, - Opcode.INVOKE_STATIC, + Opcode.INVOKE_VIRTUAL, Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, + Opcode.IPUT_OBJECT, + Opcode.CONST, + Opcode.INVOKE_VIRTUAL, + Opcode.NEW_INSTANCE, + Opcode.INVOKE_DIRECT, ), ) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch.kt index beb9d30f4..f2ec33523 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch.kt @@ -2,24 +2,38 @@ package app.revanced.patches.music.layout.minimizedplayback import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.music.layout.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint +import app.revanced.patches.music.layout.minimizedplayback.fingerprints.BackgroundPlaybackDisableFingerprint +import app.revanced.patches.music.layout.minimizedplayback.fingerprints.KidsMinimizedPlaybackPolicyControllerFingerprint import app.revanced.util.exception @Patch( - name = "Minimized playback music", - description = "Enables minimized playback on Kids music.", + name = "Minimized playback", + description = "Unlocks options for picture-in-picture and background playback.", compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], ) @Suppress("unused") -object MinimizedPlaybackPatch : BytecodePatch(setOf(MinimizedPlaybackManagerFingerprint)) { - override fun execute(context: BytecodeContext) = - MinimizedPlaybackManagerFingerprint.result?.mutableMethod?.addInstruction( +object MinimizedPlaybackPatch : BytecodePatch( + setOf( + KidsMinimizedPlaybackPolicyControllerFingerprint, + BackgroundPlaybackDisableFingerprint, + ), +) { + override fun execute(context: BytecodeContext) { + KidsMinimizedPlaybackPolicyControllerFingerprint.result?.mutableMethod?.addInstruction( + 0, + "return-void", + ) ?: throw KidsMinimizedPlaybackPolicyControllerFingerprint.exception + + BackgroundPlaybackDisableFingerprint.result?.mutableMethod?.addInstructions( 0, """ - return-void + const/4 v0, 0x1 + return v0 """, - ) ?: throw MinimizedPlaybackManagerFingerprint.exception + ) ?: throw BackgroundPlaybackDisableFingerprint.exception + } } diff --git a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/BackgroundPlaybackDisableFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/BackgroundPlaybackDisableFingerprint.kt new file mode 100644 index 000000000..d13410287 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/BackgroundPlaybackDisableFingerprint.kt @@ -0,0 +1,23 @@ +package app.revanced.patches.music.layout.minimizedplayback.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +internal object BackgroundPlaybackDisableFingerprint : MethodFingerprint( + "Z", + AccessFlags.PUBLIC or AccessFlags.STATIC, + listOf("L"), + listOf( + Opcode.CONST_4, + Opcode.IF_EQZ, + Opcode.IGET, + Opcode.AND_INT_LIT16, + Opcode.IF_EQZ, + Opcode.IGET_OBJECT, + Opcode.IF_NEZ, + Opcode.SGET_OBJECT, + Opcode.IGET, + ), +) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/MinimizedPlaybackManagerFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/KidsMinimizedPlaybackPolicyControllerFingerprint.kt similarity index 88% rename from src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/MinimizedPlaybackManagerFingerprint.kt rename to src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/KidsMinimizedPlaybackPolicyControllerFingerprint.kt index f4775805e..da6823c8a 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/MinimizedPlaybackManagerFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/KidsMinimizedPlaybackPolicyControllerFingerprint.kt @@ -5,7 +5,7 @@ import app.revanced.patcher.fingerprint.MethodFingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal object MinimizedPlaybackManagerFingerprint : MethodFingerprint( +internal object KidsMinimizedPlaybackPolicyControllerFingerprint : MethodFingerprint( "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("I", "L", "Z"), diff --git a/src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt index da41d1b35..4be4470dc 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt @@ -2,41 +2,44 @@ package app.revanced.patches.music.layout.premium import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumFingerprint -import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumParentFingerprint +import app.revanced.util.exception +import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @Patch( - name = "Hide get premium", - description = "Removes all \"Get Premium\" evidences from the avatar menu.", + name = "Hide 'Get Music Premium' label", + description = "Hides the red \"Get Music Premium\" label from the account menu.", compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], ) @Suppress("unused") -object HideGetPremiumPatch : BytecodePatch(setOf(HideGetPremiumParentFingerprint)) { +object HideGetPremiumPatch : BytecodePatch( + setOf(HideGetPremiumFingerprint), +) { override fun execute(context: BytecodeContext) { - val parentResult = HideGetPremiumParentFingerprint.result!! - HideGetPremiumFingerprint.resolve(context, parentResult.classDef) + HideGetPremiumFingerprint.result?.let { + it.mutableMethod.apply { + val insertIndex = it.scanResult.patternScanResult!!.endIndex - val startIndex = parentResult.scanResult.patternScanResult!!.startIndex + val setVisibilityInstruction = getInstruction(insertIndex) + val getPremiumViewRegister = setVisibilityInstruction.registerC + val visibilityRegister = setVisibilityInstruction.registerD - val parentMethod = parentResult.mutableMethod - parentMethod.replaceInstruction( - startIndex, - """ - const/4 v1, 0x0 - """, - ) + replaceInstruction( + insertIndex, + "const/16 v$visibilityRegister, 0x8", + ) - val result = HideGetPremiumFingerprint.result!! - val method = result.mutableMethod - method.addInstruction( - startIndex, - """ - const/16 v0, 0x8 - """, - ) + addInstruction( + insertIndex + 1, + "invoke-virtual {v$getPremiumViewRegister, v$visibilityRegister}, " + + "Landroid/view/View;->setVisibility(I)V", + ) + } + } ?: throw HideGetPremiumFingerprint.exception } } diff --git a/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumFingerprint.kt index d12628542..e97251de5 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumFingerprint.kt @@ -12,8 +12,7 @@ internal object HideGetPremiumFingerprint : MethodFingerprint( listOf( Opcode.IF_NEZ, Opcode.CONST_16, - Opcode.GOTO, - Opcode.NOP, Opcode.INVOKE_VIRTUAL, ), + listOf("FEmusic_history", "FEmusic_offline"), ) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumParentFingerprint.kt deleted file mode 100644 index 9e41ac782..000000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumParentFingerprint.kt +++ /dev/null @@ -1,22 +0,0 @@ -package app.revanced.patches.music.layout.premium.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode - -internal object HideGetPremiumParentFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf(), - listOf( - Opcode.IGET_BOOLEAN, - Opcode.CONST_4, - Opcode.IF_EQZ, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - ), - listOf("FEmusic_history"), -) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/RemoveUpgradeButtonPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/RemoveUpgradeButtonPatch.kt index 2f61db745..fed2cc6db 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/RemoveUpgradeButtonPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/RemoveUpgradeButtonPatch.kt @@ -1,16 +1,23 @@ package app.revanced.patches.music.layout.upgradebutton import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.extensions.InstructionExtensions.getInstructions +import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction +import app.revanced.patcher.extensions.newLabel import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.smali.toInstructions import app.revanced.patches.music.layout.upgradebutton.fingerprints.PivotBarConstructorFingerprint +import app.revanced.util.exception +import app.revanced.util.getReference import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction22t -import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22c import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c +import com.android.tools.smali.dexlib2.iface.reference.FieldReference @Patch( name = "Remove upgrade button", @@ -22,54 +29,56 @@ object RemoveUpgradeButtonPatch : BytecodePatch( setOf(PivotBarConstructorFingerprint), ) { override fun execute(context: BytecodeContext) { - val result = PivotBarConstructorFingerprint.result!! - val implementation = result.mutableMethod.implementation!! + PivotBarConstructorFingerprint.result?.let { + it.mutableMethod.apply { + val pivotBarElementFieldReference = getInstruction(it.scanResult.patternScanResult!!.endIndex - 1) + .getReference() - val pivotBarElementFieldRef = - (implementation.instructions[result.scanResult.patternScanResult!!.endIndex - 1] as Instruction22c).reference + val register = (getInstructions().first() as Instruction35c).registerC - val register = (implementation.instructions.first() as Instruction35c).registerC - // first compile all the needed instructions - val instructionList = """ - invoke-interface { v0 }, Ljava/util/List;->size()I - move-result v1 - const/4 v2, 0x4 - invoke-interface {v0, v2}, Ljava/util/List;->remove(I)Ljava/lang/Object; - iput-object v0, v$register, $pivotBarElementFieldRef - """.toInstructions().toMutableList() + // First compile all the needed instructions. + val instructionList = """ + invoke-interface { v0 }, Ljava/util/List;->size()I + move-result v1 + const/4 v2, 0x4 + invoke-interface {v0, v2}, Ljava/util/List;->remove(I)Ljava/lang/Object; + iput-object v0, v$register, $pivotBarElementFieldReference + """.toInstructions().toMutableList() - val endIndex = result.scanResult.patternScanResult!!.endIndex + val endIndex = it.scanResult.patternScanResult!!.endIndex - // replace the instruction to retain the label at given index - implementation.replaceInstruction( - endIndex - 1, - instructionList[0], // invoke-interface - ) - // do not forget to remove this instruction since we added it already - instructionList.removeFirst() + // Replace the instruction to retain the label at given index. + replaceInstruction( + endIndex - 1, + instructionList[0], // invoke-interface. + ) + // Do not forget to remove this instruction since we added it already. + instructionList.removeFirst() - val exitInstruction = instructionList.last() // iput-object - implementation.addInstruction( - endIndex, - exitInstruction, - ) - // do not forget to remove this instruction since we added it already - instructionList.removeLast() + val exitInstruction = instructionList.last() // iput-object + addInstruction( + endIndex, + exitInstruction, + ) + // Do not forget to remove this instruction since we added it already. + instructionList.removeLast() - // add the necessary if statement to remove the upgrade tab button in case it exists - instructionList.add( - 2, // if-le - BuilderInstruction22t( - Opcode.IF_LE, - 1, - 2, - implementation.newLabelForIndex(endIndex), - ), - ) + // Add the necessary if statement to remove the upgrade tab button in case it exists. + instructionList.add( + 2, // if-le. + BuilderInstruction22t( + Opcode.IF_LE, + 1, + 2, + newLabel(endIndex), + ), + ) - implementation.addInstructions( - endIndex, - instructionList, - ) + addInstructions( + endIndex, + instructionList, + ) + } + } ?: throw PivotBarConstructorFingerprint.exception } } diff --git a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/fingerprints/PivotBarConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/fingerprints/PivotBarConstructorFingerprint.kt index f8e6d6d3f..ee7ffbcb8 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/fingerprints/PivotBarConstructorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/fingerprints/PivotBarConstructorFingerprint.kt @@ -2,59 +2,17 @@ package app.revanced.patches.music.layout.upgradebutton.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. internal object PivotBarConstructorFingerprint : MethodFingerprint( "V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "Z"), listOf( - Opcode.INVOKE_DIRECT, - Opcode.CONST_4, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_BOOLEAN, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.GOTO, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IGET, - Opcode.CONST, - Opcode.IF_NE, - Opcode.IGET_OBJECT, - Opcode.CHECK_CAST, - Opcode.GOTO, - Opcode.SGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IGET, - Opcode.CONST, - Opcode.IF_NE, - Opcode.IGET_OBJECT, Opcode.CHECK_CAST, Opcode.INVOKE_INTERFACE, Opcode.GOTO, - Opcode.NOP, Opcode.IPUT_OBJECT, Opcode.RETURN_VOID, ), diff --git a/src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportPatch.kt index 8ad6d4a19..65d905396 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportPatch.kt @@ -2,7 +2,7 @@ package app.revanced.patches.music.misc.gms import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_NAME import app.revanced.patches.music.misc.gms.Constants.REVANCED_MUSIC_PACKAGE_NAME -import app.revanced.patches.music.misc.gms.GmsCoreSupportResourcePatch.gmsCoreVendorOption +import app.revanced.patches.music.misc.gms.GmsCoreSupportResourcePatch.gmsCoreVendorGroupIdOption import app.revanced.patches.music.misc.gms.fingerprints.* import app.revanced.patches.music.misc.integrations.IntegrationsPatch import app.revanced.patches.music.misc.integrations.fingerprints.ApplicationInitFingerprint @@ -34,5 +34,5 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch( PrimeMethodFingerprint, ), ) { - override val gmsCoreVendor by gmsCoreVendorOption + override val gmsCoreVendor by gmsCoreVendorGroupIdOption } diff --git a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/BackgroundPlayPatch.kt b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/BackgroundPlayPatch.kt index 79bed8531..a17903a2d 100644 --- a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/BackgroundPlayPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/BackgroundPlayPatch.kt @@ -1,26 +1,12 @@ package app.revanced.patches.music.premium.backgroundplay import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.annotation.CompatiblePackage -import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.music.premium.backgroundplay.fingerprints.BackgroundPlaybackDisableFingerprint -import app.revanced.util.exception - -@Patch( - name = "Background play", - description = "Enables playing music in the background.", - compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], -) -@Suppress("unused") -object BackgroundPlayPatch : BytecodePatch(setOf(BackgroundPlaybackDisableFingerprint)) { - override fun execute(context: BytecodeContext) = - BackgroundPlaybackDisableFingerprint.result?.mutableMethod?.addInstructions( - 0, - """ - const/4 v0, 0x1 - return v0 - """, - ) ?: throw BackgroundPlaybackDisableFingerprint.exception +import app.revanced.patches.music.layout.minimizedplayback.MinimizedPlaybackPatch +@Deprecated("This patch has been merged into MinimizedPlaybackPatch.") +object BackgroundPlayPatch : BytecodePatch( + dependencies = setOf(MinimizedPlaybackPatch::class), +) { + override fun execute(context: BytecodeContext) { + } } diff --git a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/fingerprints/BackgroundPlaybackDisableFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/fingerprints/BackgroundPlaybackDisableFingerprint.kt deleted file mode 100644 index 5444ebd02..000000000 --- a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/fingerprints/BackgroundPlaybackDisableFingerprint.kt +++ /dev/null @@ -1,45 +0,0 @@ -package app.revanced.patches.music.premium.backgroundplay.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode - -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. -internal object BackgroundPlaybackDisableFingerprint : MethodFingerprint( - "Z", - AccessFlags.PUBLIC or AccessFlags.STATIC, - listOf("L"), - listOf( - Opcode.CONST_4, - Opcode.IF_EQZ, - Opcode.IGET, - Opcode.AND_INT_LIT16, - Opcode.IF_EQZ, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IGET, - Opcode.CONST, - Opcode.IF_NE, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IGET, - Opcode.IF_NE, - Opcode.IGET_OBJECT, - Opcode.CHECK_CAST, - Opcode.GOTO, - Opcode.SGET_OBJECT, - Opcode.GOTO, - Opcode.CONST_4, - Opcode.IF_EQZ, - Opcode.IGET_BOOLEAN, - Opcode.IF_EQZ, - Opcode.CONST_4, - Opcode.RETURN, - Opcode.RETURN, - Opcode.RETURN, - ), -) diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/ads/BaseDisableAdsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/ads/BaseDisableAdsPatch.kt new file mode 100644 index 000000000..c8697180b --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/ads/BaseDisableAdsPatch.kt @@ -0,0 +1,19 @@ +package app.revanced.patches.reddit.customclients.ads + +import app.revanced.patcher.PatchClass +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patches.reddit.customclients.ads.fingerprints.IsAdsEnabledFingerprint +import app.revanced.util.returnEarly + +abstract class BaseDisableAdsPatch( + dependencies: Set = emptySet(), + compatiblePackages: Set, +) : BytecodePatch( + name = "Disable ads", + dependencies = dependencies, + compatiblePackages = compatiblePackages, + fingerprints = setOf(IsAdsEnabledFingerprint), +) { + override fun execute(context: BytecodeContext) = listOf(IsAdsEnabledFingerprint).returnEarly() +} diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/fingerprints/IsAdsEnabledFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/ads/fingerprints/IsAdsEnabledFingerprint.kt similarity index 80% rename from src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/fingerprints/IsAdsEnabledFingerprint.kt rename to src/main/kotlin/app/revanced/patches/reddit/customclients/ads/fingerprints/IsAdsEnabledFingerprint.kt index 97526fb62..a4c8b61d7 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/fingerprints/IsAdsEnabledFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/ads/fingerprints/IsAdsEnabledFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.reddit.customclients.syncforreddit.ads.fingerprints +package app.revanced.patches.reddit.customclients.ads.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforlemmy/ads/DisableAdsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforlemmy/ads/DisableAdsPatch.kt new file mode 100644 index 000000000..2359a40db --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforlemmy/ads/DisableAdsPatch.kt @@ -0,0 +1,10 @@ +package app.revanced.patches.reddit.customclients.syncforlemmy.ads + +import app.revanced.patches.reddit.customclients.ads.BaseDisableAdsPatch +import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.DisablePiracyDetectionPatch + +@Suppress("unused") +object DisableAdsPatch : BaseDisableAdsPatch( + dependencies = setOf(DisablePiracyDetectionPatch::class), + compatiblePackages = setOf(CompatiblePackage("com.laurencedawson.reddit_sync")), +) diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/DisableAdsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/DisableAdsPatch.kt index a8ed2045e..c43f4d32f 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/DisableAdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/ads/DisableAdsPatch.kt @@ -1,30 +1,8 @@ package app.revanced.patches.reddit.customclients.syncforreddit.ads -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.annotation.CompatiblePackage -import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.reddit.customclients.syncforreddit.ads.fingerprints.IsAdsEnabledFingerprint -import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.DisablePiracyDetectionPatch -import app.revanced.util.exception +import app.revanced.patches.reddit.customclients.ads.BaseDisableAdsPatch -@Patch( - name = "Disable ads", - dependencies = [DisablePiracyDetectionPatch::class], - compatiblePackages = [CompatiblePackage("com.laurencedawson.reddit_sync")], -) @Suppress("unused") -object DisableAdsPatch : BytecodePatch(setOf(IsAdsEnabledFingerprint)) { - override fun execute(context: BytecodeContext) { - IsAdsEnabledFingerprint.result?.mutableMethod?.apply { - addInstructions( - 0, - """ - const/4 v0, 0x0 - return v0 - """, - ) - } ?: throw IsAdsEnabledFingerprint.exception - } -} +object DisableAdsPatch : BaseDisableAdsPatch( + compatiblePackages = setOf(CompatiblePackage("io.syncapps.lemmy_sync")), +) diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportPatch.kt b/src/main/kotlin/app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportPatch.kt index 71cf283f7..f7bfcb6ef 100644 --- a/src/main/kotlin/app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportPatch.kt @@ -96,7 +96,7 @@ abstract class BaseGmsCoreSupportPatch( // Check the availability of GmsCore. mainActivityOnCreateFingerprint.result?.mutableMethod?.addInstruction( 1, // Hack to not disturb other patches (such as the integrations patch). - "invoke-static {}, Lapp/revanced/integrations/youtube/patches/GmsCoreSupport;->checkAvailability()V", + "invoke-static {}, Lapp/revanced/integrations/shared/GmsCoreSupport;->checkAvailability()V", ) ?: throw mainActivityOnCreateFingerprint.exception // Change the vendor of GmsCore in ReVanced Integrations. @@ -274,6 +274,9 @@ abstract class BaseGmsCoreSupportPatch( // fido "com.google.android.gms.fido.fido2.privileged.START", + // gass + "com.google.android.gms.gass.START", + // games "com.google.android.gms.games.service.START", "com.google.android.gms.games.PLAY_GAMES_UPGRADE", @@ -293,8 +296,18 @@ abstract class BaseGmsCoreSupportPatch( // misc "com.google.android.gms.gmscompliance.service.START", "com.google.android.gms.oss.licenses.service.START", - "com.google.android.gms.safetynet.service.START", "com.google.android.gms.tapandpay.service.BIND", + "com.google.android.gms.measurement.START", + "com.google.android.gms.languageprofile.service.START", + "com.google.android.gms.clearcut.service.START", + "com.google.android.gms.icing.LIGHTWEIGHT_INDEX_SERVICE", + + // potoken + "com.google.android.gms.potokens.service.START", + + // droidguard/ safetynet + "com.google.android.gms.droidguard.service.START", + "com.google.android.gms.safetynet.service.START", ) /** diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportResourcePatch.kt b/src/main/kotlin/app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportResourcePatch.kt index e42f33608..eef039f74 100644 --- a/src/main/kotlin/app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportResourcePatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportResourcePatch.kt @@ -24,21 +24,23 @@ abstract class BaseGmsCoreSupportResourcePatch( private val spoofedPackageSignature: String, dependencies: Set = setOf(), ) : ResourcePatch(dependencies = setOf(ChangePackageNamePatch::class, AddResourcesPatch::class) + dependencies) { - internal val gmsCoreVendorOption = + internal val gmsCoreVendorGroupIdOption = stringPatchOption( - key = "gmsCoreVendor", - default = "com.mgoogle", + key = "gmsCoreVendorGroupId", + default = "app.revanced", values = mapOf( - "Vanced" to "com.mgoogle", "ReVanced" to "app.revanced", ), - title = "GmsCore Vendor", - description = "The group id of the GmsCore vendor.", + title = "GmsCore vendor group ID", + description = "The vendor's group ID for GmsCore.", required = true, - ) { it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$")) } + ) { it!!.matches(Regex(PACKAGE_NAME_REGEX_PATTERN)) } - protected val gmsCoreVendor by gmsCoreVendorOption + protected val gmsCoreVendorGroupId by gmsCoreVendorGroupIdOption + + @Deprecated("Use gmsCoreVendorGroupId instead.", ReplaceWith("gmsCoreVendorGroupId")) + protected val gmsCoreVendor by gmsCoreVendorGroupIdOption override fun execute(context: ResourceContext) { AddResourcesPatch(BaseGmsCoreSupportResourcePatch::class) @@ -70,12 +72,12 @@ abstract class BaseGmsCoreSupportResourcePatch( // Spoof package name and signature. applicationNode.adoptChild("meta-data") { - setAttribute("android:name", "$gmsCoreVendor.android.gms.SPOOFED_PACKAGE_NAME") + setAttribute("android:name", "$gmsCoreVendorGroupId.android.gms.SPOOFED_PACKAGE_NAME") setAttribute("android:value", fromPackageName) } applicationNode.adoptChild("meta-data") { - setAttribute("android:name", "$gmsCoreVendor.android.gms.SPOOFED_PACKAGE_SIGNATURE") + setAttribute("android:name", "$gmsCoreVendorGroupId.android.gms.SPOOFED_PACKAGE_SIGNATURE") setAttribute("android:value", spoofedPackageSignature) } @@ -83,7 +85,7 @@ abstract class BaseGmsCoreSupportResourcePatch( applicationNode.adoptChild("meta-data") { // TODO: The name of this metadata should be dynamic. setAttribute("android:name", "app.revanced.MICROG_PACKAGE_NAME") - setAttribute("android:value", "$gmsCoreVendor.android.gms") + setAttribute("android:value", "$gmsCoreVendorGroupId.android.gms") } } } @@ -110,11 +112,16 @@ abstract class BaseGmsCoreSupportResourcePatch( "$packageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION", ).replace( "com.google.android.c2dm", - "$gmsCoreVendor.android.c2dm", + "$gmsCoreVendorGroupId.android.c2dm", ).replace( "", - "", + "", ), ) } + + private companion object { + private const val VANCED_VENDOR = "com.mgoogle" + private const val PACKAGE_NAME_REGEX_PATTERN = "^[a-z]\\w*(\\.[a-z]\\w*)+\$" + } } diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch.kt index eb7f7e872..c1c849c01 100644 --- a/src/main/kotlin/app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch.kt @@ -49,7 +49,8 @@ abstract class BaseIntegrationsPatch( opcodes: Iterable? = null, strings: Iterable? = null, customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null, - private val contextRegisterResolver: (Method) -> Int = object : IRegisterResolver {}, + private val insertIndexResolver: ((Method) -> Int) = object : IHookInsertIndexResolver {}, + private val contextRegisterResolver: (Method) -> Int = object : IRegisterResolver {} ) : MethodFingerprint( returnType, accessFlags, @@ -58,18 +59,45 @@ abstract class BaseIntegrationsPatch( strings, customFingerprint, ) { + @Deprecated("Previous constructor that is missing the insert index." + + "Here only for binary compatibility, " + + "and this can be removed after the next major version update.") + constructor( + returnType: String? = null, + accessFlags: Int? = null, + parameters: Iterable? = null, + opcodes: Iterable? = null, + strings: Iterable? = null, + customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null, + contextRegisterResolver: (Method) -> Int = object : IRegisterResolver {} + ) : this( + returnType, + accessFlags, + parameters, + opcodes, + strings, + customFingerprint, + object : IHookInsertIndexResolver {}, + contextRegisterResolver + ) + fun invoke(integrationsDescriptor: String) { result?.mutableMethod?.let { method -> + val insertIndex = insertIndexResolver(method) val contextRegister = contextRegisterResolver(method) method.addInstruction( - 0, - "sput-object v$contextRegister, " + - "$integrationsDescriptor->context:Landroid/content/Context;", + insertIndex, + "invoke-static/range { v$contextRegister .. v$contextRegister }, " + + "$integrationsDescriptor->setContext(Landroid/content/Context;)V", ) } ?: throw PatchException("Could not find hook target fingerprint.") } + interface IHookInsertIndexResolver : (Method) -> Int { + override operator fun invoke(method: Method) = 0 + } + interface IRegisterResolver : (Method) -> Int { override operator fun invoke(method: Method) = method.implementation!!.registerCount - 1 } 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 06414494b..65c634a0a 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 @@ -1,10 +1,14 @@ package app.revanced.patches.tiktok.misc.integrations.fingerprints +import app.revanced.patcher.extensions.or import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch.IntegrationsFingerprint +import com.android.tools.smali.dexlib2.AccessFlags internal object InitFingerprint : IntegrationsFingerprint( + accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("/AwemeHostApplication;") && - methodDef.name == "onCreate" + methodDef.name == "" }, -) + insertIndexResolver = { 1 } // Insert after call to super class. +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/general/HideAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/general/HideAdsPatch.kt index b73927b67..063f033ec 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/ad/general/HideAdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/ad/general/HideAdsPatch.kt @@ -36,9 +36,13 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" ], ), ], diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/HideGetPremiumPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/HideGetPremiumPatch.kt index 175991c2c..a90956e0f 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/HideGetPremiumPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/HideGetPremiumPatch.kt @@ -19,8 +19,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class], compatiblePackages = [ CompatiblePackage( - "com.google.android.youtube", - [ + "com.google.android.youtube", [ "18.32.39", "18.37.36", "18.38.44", @@ -31,12 +30,16 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) object HideGetPremiumPatch : BytecodePatch(setOf(GetPremiumViewFingerprint)) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = @@ -46,7 +49,7 @@ object HideGetPremiumPatch : BytecodePatch(setOf(GetPremiumViewFingerprint)) { AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.ADS.addPreferences( - SwitchPreference("revanced_hide_get_premium"), + SwitchPreference("revanced_hide_get_premium") ) GetPremiumViewFingerprint.result?.let { @@ -70,7 +73,7 @@ object HideGetPremiumPatch : BytecodePatch(setOf(GetPremiumViewFingerprint)) { :allow nop # Layout width/height is then passed to a protected class method. - """, + """ ) } } ?: throw GetPremiumViewFingerprint.exception diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/video/VideoAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/video/VideoAdsPatch.kt index 2a1bda24b..06e496e0e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/ad/video/VideoAdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/ad/video/VideoAdsPatch.kt @@ -19,7 +19,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch dependencies = [ IntegrationsPatch::class, SettingsPatch::class, - AddResourcesPatch::class, + AddResourcesPatch::class ], compatiblePackages = [ CompatiblePackage( @@ -35,35 +35,38 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object VideoAdsPatch : BytecodePatch( - setOf(LoadVideoAdsFingerprint), + setOf(LoadVideoAdsFingerprint) ) { override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.ADS.addPreferences( - SwitchPreference("revanced_hide_video_ads"), + SwitchPreference("revanced_hide_video_ads") ) val loadVideoAdsFingerprintMethod = LoadVideoAdsFingerprint.result!!.mutableMethod loadVideoAdsFingerprintMethod.addInstructionsWithLabels( - 0, - """ + 0, """ invoke-static { }, Lapp/revanced/integrations/youtube/patches/VideoAdsPatch;->shouldShowAds()Z move-result v0 if-nez v0, :show_video_ads return-void """, - ExternalLabel("show_video_ads", loadVideoAdsFingerprintMethod.getInstruction(0)), + ExternalLabel("show_video_ads", loadVideoAdsFingerprintMethod.getInstruction(0)) ) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/CopyVideoUrlBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/CopyVideoUrlBytecodePatch.kt index 894d30855..89398b8d2 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/CopyVideoUrlBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/copyvideourl/CopyVideoUrlBytecodePatch.kt @@ -23,9 +23,13 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" ], ), ], @@ -39,7 +43,6 @@ object CopyVideoUrlBytecodePatch : BytecodePatch(emptySet()) { ) override fun execute(context: BytecodeContext) { - // Initialize buttons and inject visibility control BUTTONS_DESCRIPTORS.forEach { descriptor -> PlayerControlsBytecodePatch.initializeControl("$descriptor->initializeButton(Landroid/view/View;)V") PlayerControlsBytecodePatch.injectVisibilityCheckCall("$descriptor->changeVisibility(Z)V") diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/dialog/RemoveViewerDiscretionDialogPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/dialog/RemoveViewerDiscretionDialogPatch.kt index f7ba49e5e..7fdacaeff 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/dialog/RemoveViewerDiscretionDialogPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/dialog/RemoveViewerDiscretionDialogPatch.kt @@ -17,12 +17,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @Patch( name = "Remove viewer discretion dialog", description = "Adds an option to remove the dialog that appears when opening a video that has been age-restricted " + - "by accepting it automatically. This does not bypass the age restriction.", + "by accepting it automatically. This does not bypass the age restriction.", dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class], compatiblePackages = [ CompatiblePackage( - "com.google.android.youtube", - [ + "com.google.android.youtube", [ "18.32.39", "18.37.36", "18.38.44", @@ -33,26 +32,30 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object RemoveViewerDiscretionDialogPatch : BytecodePatch( - setOf(CreateDialogFingerprint), + setOf(CreateDialogFingerprint) ) { private const val INTEGRATIONS_METHOD_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/RemoveViewerDiscretionDialogPatch;->" + - "confirmDialog(Landroid/app/AlertDialog;)V" + "confirmDialog(Landroid/app/AlertDialog;)V" override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences( - SwitchPreference("revanced_remove_viewer_discretion_dialog"), + SwitchPreference("revanced_remove_viewer_discretion_dialog") ) CreateDialogFingerprint.result?.mutableMethod?.apply { diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsPatch.kt new file mode 100644 index 000000000..6147a3d54 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsPatch.kt @@ -0,0 +1,79 @@ +package app.revanced.patches.youtube.interaction.downloads + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.annotation.CompatiblePackage +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patches.youtube.interaction.downloads.fingerprints.OfflineVideoEndpointFingerprint +import app.revanced.patches.youtube.misc.playercontrols.PlayerControlsBytecodePatch +import app.revanced.patches.youtube.shared.fingerprints.MainActivityFingerprint +import app.revanced.patches.youtube.video.information.VideoInformationPatch +import app.revanced.util.resultOrThrow + +@Patch( + name = "Downloads", + description = "Adds support to download videos with an external downloader app " + + "using the in-app download button or a video player action button.", + dependencies = [ + DownloadsResourcePatch::class, + PlayerControlsBytecodePatch::class, + VideoInformationPatch::class, + ], + compatiblePackages = [ + CompatiblePackage( + "com.google.android.youtube", + [ + "18.48.39", + "18.49.37", + "19.01.34", + "19.02.39", + "19.03.36", + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ], + ), + ], +) +@Suppress("unused") +object DownloadsPatch : BytecodePatch( + setOf( + OfflineVideoEndpointFingerprint, + MainActivityFingerprint + ) +) { + private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/DownloadsPatch;" + private const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/youtube/videoplayer/ExternalDownloadButton;" + + override fun execute(context: BytecodeContext) { + PlayerControlsBytecodePatch.initializeControl("$BUTTON_DESCRIPTOR->initializeButton(Landroid/view/View;)V") + PlayerControlsBytecodePatch.injectVisibilityCheckCall("$BUTTON_DESCRIPTOR->changeVisibility(Z)V") + + // Main activity is used to launch downloader intent. + MainActivityFingerprint.resultOrThrow().mutableMethod.apply { + addInstruction( + implementation!!.instructions.lastIndex, + "invoke-static { p0 }, $INTEGRATIONS_CLASS_DESCRIPTOR->activityCreated(Landroid/app/Activity;)V" + ) + } + + OfflineVideoEndpointFingerprint.resultOrThrow().mutableMethod.apply { + addInstructionsWithLabels( + 0, + """ + invoke-static/range {p3 .. p3}, $INTEGRATIONS_CLASS_DESCRIPTOR->inAppDownloadButtonOnClick(Ljava/lang/String;)Z + move-result v0 + if-eqz v0, :show_native_downloader + return-void + :show_native_downloader + nop + """ + ) + } + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/ExternalDownloadsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsResourcePatch.kt similarity index 92% rename from src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/ExternalDownloadsResourcePatch.kt rename to src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsResourcePatch.kt index e24b7e6c1..24285e53b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/ExternalDownloadsResourcePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/DownloadsResourcePatch.kt @@ -21,7 +21,7 @@ import app.revanced.util.copyResources AddResourcesPatch::class, ], ) -internal object ExternalDownloadsResourcePatch : ResourcePatch() { +internal object DownloadsResourcePatch : ResourcePatch() { override fun execute(context: ResourceContext) { AddResourcesPatch(this::class) @@ -31,6 +31,7 @@ internal object ExternalDownloadsResourcePatch : ResourcePatch() { sorting = Sorting.UNSORTED, preferences = setOf( SwitchPreference("revanced_external_downloader"), + SwitchPreference("revanced_external_downloader_action_button"), TextPreference("revanced_external_downloader_name", inputType = InputType.TEXT), ), ), diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/ExternalDownloadsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/ExternalDownloadsBytecodePatch.kt deleted file mode 100644 index fdda9fdbe..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/ExternalDownloadsBytecodePatch.kt +++ /dev/null @@ -1,54 +0,0 @@ -package app.revanced.patches.youtube.interaction.downloads - -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.annotation.CompatiblePackage -import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.youtube.misc.playercontrols.PlayerControlsBytecodePatch -import app.revanced.patches.youtube.video.information.VideoInformationPatch - -@Patch( - name = "External downloads", - description = "Adds support to download and save YouTube videos using an external downloader app.", - dependencies = [ - ExternalDownloadsResourcePatch::class, - PlayerControlsBytecodePatch::class, - VideoInformationPatch::class, - ], - compatiblePackages = [ - CompatiblePackage( - "com.google.android.youtube", - [ - "18.48.39", - "18.49.37", - "19.01.34", - "19.02.39", - "19.03.35", - "19.03.36", - "19.04.37", - ], - ), - ], -) -@Suppress("unused") -object ExternalDownloadsBytecodePatch : BytecodePatch(emptySet()) { - private const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/youtube/videoplayer/ExternalDownloadButton;" - - override fun execute(context: BytecodeContext) { - /* - initialize the control - */ - - PlayerControlsBytecodePatch.initializeControl( - "$BUTTON_DESCRIPTOR->initializeButton(Landroid/view/View;)V", - ) - - /* - add code to change the visibility of the control - */ - - PlayerControlsBytecodePatch.injectVisibilityCheckCall( - "$BUTTON_DESCRIPTOR->changeVisibility(Z)V", - ) - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/OfflineVideoEndpointFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/OfflineVideoEndpointFingerprint.kt new file mode 100644 index 000000000..f28bc556b --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/fingerprints/OfflineVideoEndpointFingerprint.kt @@ -0,0 +1,16 @@ +package app.revanced.patches.youtube.interaction.downloads.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags + +internal object OfflineVideoEndpointFingerprint : MethodFingerprint( + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + returnType = "V", + parameters = listOf( + "Ljava/util/Map;", + "L", + "Ljava/lang/String", // VideoId + "L"), + strings = listOf("Object is not an offlineable video: ") +) diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/DisablePreciseSeekingGesturePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/DisablePreciseSeekingGesturePatch.kt index 9773ebc39..e18a8f076 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/DisablePreciseSeekingGesturePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/DisablePreciseSeekingGesturePatch.kt @@ -32,26 +32,30 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object DisablePreciseSeekingGesturePatch : BytecodePatch( - setOf(IsSwipingUpFingerprint), + setOf(IsSwipingUpFingerprint) ) { private const val INTEGRATIONS_METHOD_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/DisablePreciseSeekingGesturePatch;->" + - "disableGesture(Landroid/view/VelocityTracker;Landroid/view/MotionEvent;)V" + "disableGesture(Landroid/view/VelocityTracker;Landroid/view/MotionEvent;)V" override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.SEEKBAR.addPreferences( - SwitchPreference("revanced_disable_precise_seeking_gesture"), + SwitchPreference("revanced_disable_precise_seeking_gesture") ) IsSwipingUpFingerprint.result?.let { @@ -64,9 +68,9 @@ object DisablePreciseSeekingGesturePatch : BytecodePatch( replaceInstruction( addMovementIndex, - "invoke-static {v$trackerRegister, v$eventRegister}, $INTEGRATIONS_METHOD_DESCRIPTOR", + "invoke-static {v$trackerRegister, v$eventRegister}, $INTEGRATIONS_METHOD_DESCRIPTOR" ) } } ?: throw IsSwipingUpFingerprint.exception } -} +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingPatch.kt index 82c7cb2dd..3c4be5ad0 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingPatch.kt @@ -22,8 +22,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference name = "Seekbar tapping", description = "Adds an option to enable tap-to-seek on the seekbar of the video player.", dependencies = [ - IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class, - ], + IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class], compatiblePackages = [ CompatiblePackage( "com.google.android.youtube", @@ -35,25 +34,29 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object EnableSeekbarTappingPatch : BytecodePatch( setOf( OnTouchEventHandlerFingerprint, - SeekbarTappingFingerprint, - ), + SeekbarTappingFingerprint + ) ) { override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.SEEKBAR.addPreferences( - SwitchPreference("revanced_seekbar_tapping"), + SwitchPreference("revanced_seekbar_tapping") ) // Find the required methods to tap the seekbar. @@ -95,9 +98,9 @@ object EnableSeekbarTappingPatch : BytecodePatch( ${oMethod.toInvokeInstructionString()} ${nMethod.toInvokeInstructionString()} """, - ExternalLabel("disabled", getInstruction(insertIndex)), + ExternalLabel("disabled", getInstruction(insertIndex)) ) } } ?: throw SeekbarTappingFingerprint.exception } -} +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSlideToSeekPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSlideToSeekPatch.kt index ba6bef4cf..eb5ef93cd 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSlideToSeekPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSlideToSeekPatch.kt @@ -30,20 +30,24 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) ], - use = false, + use = false ) @Suppress("unused") object EnableSlideToSeekPatch : BytecodePatch( setOf( SlideToSeekFingerprint, - DoubleSpeedSeekNoticeFingerprint, - ), + DoubleSpeedSeekNoticeFingerprint + ) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/SlideToSeekPatch;" @@ -51,14 +55,14 @@ object EnableSlideToSeekPatch : BytecodePatch( AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.SEEKBAR.addPreferences( - SwitchPreference("revanced_slide_to_seek"), + SwitchPreference("revanced_slide_to_seek") ) arrayOf( // Restore the behaviour to slide to seek. SlideToSeekFingerprint, // Disable the double speed seek notice. - DoubleSpeedSeekNoticeFingerprint, + DoubleSpeedSeekNoticeFingerprint ).map { it.result ?: throw it.exception }.forEach { @@ -72,9 +76,9 @@ object EnableSlideToSeekPatch : BytecodePatch( """ invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->isSlideToSeekDisabled()Z move-result v$isEnabledRegister - """, + """ ) } } } -} +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsBytecodePatch.kt index 5b7f52879..5e21c6074 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsBytecodePatch.kt @@ -20,7 +20,7 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod dependencies = [ IntegrationsPatch::class, PlayerTypeHookPatch::class, - SwipeControlsResourcePatch::class, + SwipeControlsResourcePatch::class ], compatiblePackages = [ CompatiblePackage( @@ -36,19 +36,23 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object SwipeControlsBytecodePatch : BytecodePatch( setOf( MainActivityFingerprint, - SwipeControlsHostActivityFingerprint, - ), + SwipeControlsHostActivityFingerprint + ) ) { override fun execute(context: BytecodeContext) { val wrapperClass = SwipeControlsHostActivityFingerprint.result!!.mutableClass @@ -70,9 +74,9 @@ object SwipeControlsBytecodePatch : BytecodePatch( accessFlags and AccessFlags.FINAL.value.inv(), annotations, hiddenApiRestrictions, - implementation, + implementation ).toMutable() } } } -} +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/AutoCaptionsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/AutoCaptionsPatch.kt index 543c51116..00f15cab3 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/AutoCaptionsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/AutoCaptionsPatch.kt @@ -15,6 +15,7 @@ import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.settings.SettingsPatch import app.revanced.util.exception + @Patch( name = "Disable auto captions", description = "Adds an option to disable captions from being automatically enabled.", @@ -33,34 +34,38 @@ import app.revanced.util.exception "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) ], ) @Suppress("unused") object AutoCaptionsPatch : BytecodePatch( - setOf(StartVideoInformerFingerprint, SubtitleButtonControllerFingerprint, SubtitleTrackFingerprint), + setOf(StartVideoInformerFingerprint, SubtitleButtonControllerFingerprint, SubtitleTrackFingerprint) ) { override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.PLAYER.addPreferences( - SwitchPreference("revanced_auto_captions"), + SwitchPreference("revanced_auto_captions") ) mapOf( StartVideoInformerFingerprint to 0, - SubtitleButtonControllerFingerprint to 1, + SubtitleButtonControllerFingerprint to 1 ).forEach { (fingerprint, enabled) -> fingerprint.result?.mutableMethod?.addInstructions( 0, """ const/4 v0, 0x$enabled sput-boolean v0, Lapp/revanced/integrations/youtube/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z - """, + """ ) ?: throw fingerprint.exception } @@ -76,7 +81,7 @@ object AutoCaptionsPatch : BytecodePatch( return v0 :auto_captions_enabled nop - """, + """ ) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/HideButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/HideButtonsPatch.kt index c7a1b85aa..2a6284827 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/HideButtonsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/action/HideButtonsPatch.kt @@ -17,7 +17,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch dependencies = [ ResourceMappingPatch::class, LithoFilterPatch::class, - AddResourcesPatch::class, + AddResourcesPatch::class ], compatiblePackages = [ CompatiblePackage( @@ -33,12 +33,16 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object HideButtonsPatch : ResourcePatch() { @@ -60,9 +64,9 @@ object HideButtonsPatch : ResourcePatch() { SwitchPreference("revanced_hide_thanks_button"), SwitchPreference("revanced_hide_clip_button"), SwitchPreference("revanced_hide_playlist_button"), - SwitchPreference("revanced_hide_shop_button"), + SwitchPreference("revanced_hide_shop_button") ), - ), + ) ) LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR) diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/HideAutoplayButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/HideAutoplayButtonPatch.kt index 2e5a41770..d96caab79 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/HideAutoplayButtonPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/HideAutoplayButtonPatch.kt @@ -27,7 +27,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference IntegrationsPatch::class, SettingsPatch::class, ResourceMappingPatch::class, - AddResourcesPatch::class, + AddResourcesPatch::class ], compatiblePackages = [ CompatiblePackage( @@ -43,22 +43,26 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object HideAutoplayButtonPatch : BytecodePatch( - setOf(LayoutConstructorFingerprint), + setOf(LayoutConstructorFingerprint) ) { override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.PLAYER.addPreferences( - SwitchPreference("revanced_hide_autoplay_button"), + SwitchPreference("revanced_hide_autoplay_button") ) LayoutConstructorFingerprint.result?.mutableMethod?.apply { @@ -86,8 +90,8 @@ object HideAutoplayButtonPatch : BytecodePatch( move-result v$clobberRegister if-eqz v$clobberRegister, :hidden """, - ExternalLabel("hidden", jumpInstruction), + ExternalLabel("hidden", jumpInstruction) ) } ?: throw LayoutConstructorFingerprint.exception } -} +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/HideCaptionsButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/HideCaptionsButtonPatch.kt index 10363cb7d..88e856686 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/HideCaptionsButtonPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/captions/HideCaptionsButtonPatch.kt @@ -18,7 +18,7 @@ import com.android.tools.smali.dexlib2.Opcode dependencies = [ IntegrationsPatch::class, SettingsPatch::class, - AddResourcesPatch::class, + AddResourcesPatch::class ], compatiblePackages = [ CompatiblePackage( @@ -34,22 +34,26 @@ import com.android.tools.smali.dexlib2.Opcode "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object HideCaptionsButtonPatch : BytecodePatch( - setOf(SubtitleButtonControllerFingerprint), + setOf(SubtitleButtonControllerFingerprint) ) { override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.PLAYER.addPreferences( - SwitchPreference("revanced_hide_captions_button"), + SwitchPreference("revanced_hide_captions_button") ) val subtitleButtonControllerMethod = SubtitleButtonControllerFingerprint.result!!.mutableMethod @@ -63,7 +67,7 @@ object HideCaptionsButtonPatch : BytecodePatch( insertIndex, """ invoke-static {v0}, Lapp/revanced/integrations/youtube/patches/HideCaptionsButtonPatch;->hideCaptionsButton(Landroid/widget/ImageView;)V - """, + """ ) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt index a8ac8121b..c660344de 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt @@ -10,10 +10,10 @@ import app.revanced.patches.all.misc.resources.AddResourcesPatch import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting import app.revanced.patches.shared.misc.settings.preference.SwitchPreference -import app.revanced.patches.youtube.layout.buttons.navigation.fingerprints.* -import app.revanced.patches.youtube.layout.buttons.navigation.utils.InjectionUtils.REGISTER_TEMPLATE_REPLACEMENT -import app.revanced.patches.youtube.layout.buttons.navigation.utils.InjectionUtils.injectHook +import app.revanced.patches.youtube.layout.buttons.navigation.fingerprints.ANDROID_AUTOMOTIVE_STRING +import app.revanced.patches.youtube.layout.buttons.navigation.fingerprints.AddCreateButtonViewFingerprint import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch +import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch import app.revanced.patches.youtube.misc.settings.SettingsPatch import app.revanced.util.exception import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @@ -24,8 +24,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction dependencies = [ IntegrationsPatch::class, SettingsPatch::class, - ResolvePivotBarFingerprintsPatch::class, AddResourcesPatch::class, + NavigationBarHookPatch::class, ], compatiblePackages = [ CompatiblePackage( @@ -41,9 +41,13 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37", ], ), ], @@ -72,53 +76,7 @@ object NavigationButtonsPatch : BytecodePatch( ), ) - /* - * Resolve fingerprints - */ - - val initializeButtonsResult = InitializeButtonsFingerprint.result!! - - val fingerprintResults = - arrayOf(PivotBarEnumFingerprint, PivotBarButtonsViewFingerprint) - .onEach { - if (!it.resolve( - context, - initializeButtonsResult.mutableMethod, - initializeButtonsResult.mutableClass, - ) - ) { - throw it.exception - } - } - .map { it.result!!.scanResult.patternScanResult!! } - - val enumScanResult = fingerprintResults[0] - val buttonViewResult = fingerprintResults[1] - - val enumHookInsertIndex = enumScanResult.startIndex + 2 - val buttonHookInsertIndex = buttonViewResult.endIndex - - /* - * Inject hooks - */ - - val enumHook = "sput-object v$REGISTER_TEMPLATE_REPLACEMENT, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->lastNavigationButton:Ljava/lang/Enum;" - val buttonHook = "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->hideButton(Landroid/view/View;)V" - - // Inject bottom to top to not mess up the indices - mapOf( - buttonHook to buttonHookInsertIndex, - enumHook to enumHookInsertIndex, - ).forEach { (hook, insertIndex) -> - initializeButtonsResult.mutableMethod.injectHook(hook, insertIndex) - } - - /* - * Hide create or switch it with notifications buttons. - */ - + // Switch create with notifications button. AddCreateButtonViewFingerprint.result?.let { it.mutableMethod.apply { val stringIndex = it.scanResult.stringsScanResult!!.matches.find { match -> @@ -126,7 +84,8 @@ object NavigationButtonsPatch : BytecodePatch( }!!.index val conditionalCheckIndex = stringIndex - 1 - val conditionRegister = getInstruction(conditionalCheckIndex).registerA + val conditionRegister = + getInstruction(conditionalCheckIndex).registerA addInstructions( conditionalCheckIndex, @@ -138,26 +97,7 @@ object NavigationButtonsPatch : BytecodePatch( } } ?: throw AddCreateButtonViewFingerprint.exception - /* - * Resolve fingerprints - */ - - InitializeButtonsFingerprint.result!!.let { - if (!PivotBarCreateButtonViewFingerprint.resolve(context, it.mutableMethod, it.mutableClass)) { - throw PivotBarCreateButtonViewFingerprint.exception - } - } - - PivotBarCreateButtonViewFingerprint.result!!.apply { - val insertIndex = scanResult.patternScanResult!!.endIndex - - /* - * Inject hooks - */ - val hook = "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->hideCreateButton(Landroid/view/View;)V" - - mutableMethod.injectHook(hook, insertIndex) - } + // Hook navigation button created, in order to hide them. + NavigationBarHookPatch.hookNavigationButtonCreated(INTEGRATIONS_CLASS_DESCRIPTOR) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/ResolvePivotBarFingerprintsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/ResolvePivotBarFingerprintsPatch.kt deleted file mode 100644 index 241a656f0..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/ResolvePivotBarFingerprintsPatch.kt +++ /dev/null @@ -1,38 +0,0 @@ -package app.revanced.patches.youtube.layout.buttons.navigation - -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException -import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.shared.misc.mapping.ResourceMappingPatch -import app.revanced.patches.youtube.layout.buttons.navigation.fingerprints.InitializeButtonsFingerprint -import app.revanced.patches.youtube.layout.buttons.navigation.fingerprints.PivotBarConstructorFingerprint -import app.revanced.util.exception - -@Patch( - description = "Resolves necessary fingerprints.", - dependencies = [ResourceMappingPatch::class], -) -internal object ResolvePivotBarFingerprintsPatch : BytecodePatch( - setOf(PivotBarConstructorFingerprint), -) { - internal var imageOnlyTabResourceId: Long = -1 - - override fun execute(context: BytecodeContext) { - // imageOnlyTabResourceId is used in InitializeButtonsFingerprint fingerprint - ResourceMappingPatch.resourceMappings.find { it.type == "layout" && it.name == "image_only_tab" } - ?.let { imageOnlyTabResourceId = it.id } ?: throw PatchException("Failed to find resource") - - PivotBarConstructorFingerprint.result?.let { - // Resolve InitializeButtonsFingerprint on the class of the method - // which PivotBarConstructorFingerprint resolved to - if (!InitializeButtonsFingerprint.resolve( - context, - it.classDef, - ) - ) { - throw InitializeButtonsFingerprint.exception - } - } ?: throw PivotBarConstructorFingerprint.exception - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarButtonsViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarButtonsViewFingerprint.kt deleted file mode 100644 index 00e5e6b6f..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarButtonsViewFingerprint.kt +++ /dev/null @@ -1,12 +0,0 @@ -package app.revanced.patches.youtube.layout.buttons.navigation.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.Opcode - -internal object PivotBarButtonsViewFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.INVOKE_VIRTUAL_RANGE, - Opcode.MOVE_RESULT_OBJECT, // target reference - Opcode.GOTO, - ), -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarCreateButtonViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarCreateButtonViewFingerprint.kt deleted file mode 100644 index 749400c21..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarCreateButtonViewFingerprint.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.buttons.navigation.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.Opcode - -internal object PivotBarCreateButtonViewFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.INVOKE_DIRECT_RANGE, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - ), -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarEnumFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarEnumFingerprint.kt deleted file mode 100644 index 1e3756c68..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarEnumFingerprint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package app.revanced.patches.youtube.layout.buttons.navigation.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.Opcode - -internal object PivotBarEnumFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IF_NEZ, // target reference - Opcode.SGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - ), -) 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 deleted file mode 100644 index 0240c567e..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/utils/InjectionUtils.kt +++ /dev/null @@ -1,30 +0,0 @@ -package app.revanced.patches.youtube.layout.buttons.navigation.utils - -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import com.android.tools.smali.dexlib2.Opcode.MOVE_RESULT_OBJECT -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction - -internal object InjectionUtils { - const val REGISTER_TEMPLATE_REPLACEMENT: String = "REGISTER_INDEX" - - /** - * Injects an instruction into insertIndex of the hook. - * @param hook The hook to insert. - * @param insertIndex The index to insert the instruction at. - * [MOVE_RESULT_OBJECT] has to be the previous instruction before [insertIndex]. - */ - fun MutableMethod.injectHook(hook: String, insertIndex: Int) { - val injectTarget = this - - // Register to pass to the hook - val registerIndex = insertIndex - 1 // MOVE_RESULT_OBJECT is always the previous instruction - val register = injectTarget.getInstruction(registerIndex).registerA - - injectTarget.addInstruction( - insertIndex, - hook.replace("REGISTER_INDEX", register.toString()), - ) - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/HidePlayerButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/HidePlayerButtonsPatch.kt index ff5d3c18c..b51f3270e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/HidePlayerButtonsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/player/hide/HidePlayerButtonsPatch.kt @@ -22,7 +22,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction3rc dependencies = [ IntegrationsPatch::class, SettingsPatch::class, - AddResourcesPatch::class, + AddResourcesPatch::class ], compatiblePackages = [ CompatiblePackage( @@ -38,22 +38,26 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction3rc "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object HidePlayerButtonsPatch : BytecodePatch( - setOf(PlayerControlsVisibilityModelFingerprint), + setOf(PlayerControlsVisibilityModelFingerprint) ) { override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.PLAYER.addPreferences( - SwitchPreference("revanced_hide_player_buttons"), + SwitchPreference("revanced_hide_player_buttons") ) PlayerControlsVisibilityModelFingerprint.result?.apply { @@ -72,7 +76,7 @@ object HidePlayerButtonsPatch : BytecodePatch( invoke-static { v$hasPreviousParameterRegister }, Lapp/revanced/integrations/youtube/patches/HidePlayerButtonsPatch;->previousOrNextButtonIsVisible(Z)Z move-result v$hasPreviousParameterRegister - """, + """ ) } ?: throw PlayerControlsVisibilityModelFingerprint.exception } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/AlbumCardsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/AlbumCardsPatch.kt index a19bb1d2a..b11b24435 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/AlbumCardsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/albumcards/AlbumCardsPatch.kt @@ -1,5 +1,6 @@ package app.revanced.patches.youtube.layout.hide.albumcards +import app.revanced.util.exception import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction @@ -8,7 +9,6 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.youtube.layout.hide.albumcards.fingerprints.AlbumCardsFingerprint import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch -import app.revanced.util.exception import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @Patch( @@ -16,7 +16,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction description = "Adds an option to hide album cards below artist descriptions.", dependencies = [ IntegrationsPatch::class, - AlbumCardsResourcePatch::class, + AlbumCardsResourcePatch::class ], compatiblePackages = [ CompatiblePackage( @@ -32,16 +32,20 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object AlbumCardsPatch : BytecodePatch( - setOf(AlbumCardsFingerprint), + setOf(AlbumCardsFingerprint) ) { override fun execute(context: BytecodeContext) { AlbumCardsFingerprint.result?.let { @@ -54,9 +58,9 @@ object AlbumCardsPatch : BytecodePatch( addInstruction( insertIndex, "invoke-static {v$albumCardViewRegister}, " + - "Lapp/revanced/integrations/youtube/patches/HideAlbumCardsPatch;" + - "->" + - "hideAlbumCard(Landroid/view/View;)V", + "Lapp/revanced/integrations/youtube/patches/HideAlbumCardsPatch;" + + "->" + + "hideAlbumCard(Landroid/view/View;)V" ) } } ?: throw AlbumCardsFingerprint.exception diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/BreakingNewsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/BreakingNewsPatch.kt index f6a6790ed..34e2232bb 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/BreakingNewsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/breakingnews/BreakingNewsPatch.kt @@ -1,5 +1,6 @@ package app.revanced.patches.youtube.layout.hide.breakingnews +import app.revanced.util.exception import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction @@ -8,7 +9,6 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.youtube.layout.hide.breakingnews.fingerprints.BreakingNewsFingerprint import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch -import app.revanced.util.exception import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @Patch( @@ -16,7 +16,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction description = "Adds an option to hide the breaking news shelf on the homepage tab.", dependencies = [ IntegrationsPatch::class, - BreakingNewsResourcePatch::class, + BreakingNewsResourcePatch::class ], compatiblePackages = [ CompatiblePackage( @@ -32,16 +32,20 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object BreakingNewsPatch : BytecodePatch( - setOf(BreakingNewsFingerprint), + setOf(BreakingNewsFingerprint) ) { override fun execute(context: BytecodeContext) { BreakingNewsFingerprint.result?.let { @@ -59,9 +63,11 @@ object BreakingNewsPatch : BytecodePatch( Lapp/revanced/integrations/youtube/patches/HideBreakingNewsPatch; -> hideBreakingNews(Landroid/view/View;)V - """, + """ ) } + } ?: throw BreakingNewsFingerprint.exception + } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/CommentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/CommentsPatch.kt index 417c247b0..9cdb9c9b9 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/CommentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/comments/CommentsPatch.kt @@ -16,7 +16,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch dependencies = [ SettingsPatch::class, LithoFilterPatch::class, - AddResourcesPatch::class, + AddResourcesPatch::class ], compatiblePackages = [ CompatiblePackage( @@ -32,12 +32,16 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object CommentsPatch : ResourcePatch() { @@ -52,9 +56,9 @@ object CommentsPatch : ResourcePatch() { "revanced_comments_screen", preferences = setOf( SwitchPreference("revanced_hide_comments_section"), - SwitchPreference("revanced_hide_preview_comment"), - ), - ), + SwitchPreference("revanced_hide_preview_comment") + ) + ) ) LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR) diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/CrowdfundingBoxPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/CrowdfundingBoxPatch.kt index 265eb46fb..b429d69a6 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/CrowdfundingBoxPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/CrowdfundingBoxPatch.kt @@ -1,5 +1,6 @@ package app.revanced.patches.youtube.layout.hide.crowdfundingbox +import app.revanced.util.exception import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction @@ -8,7 +9,6 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.youtube.layout.hide.crowdfundingbox.fingerprints.CrowdfundingBoxFingerprint import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch -import app.revanced.util.exception import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction @Patch( @@ -16,7 +16,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction description = "Adds an option to hide the crowdfunding box between the player and video description.", dependencies = [ IntegrationsPatch::class, - CrowdfundingBoxResourcePatch::class, + CrowdfundingBoxResourcePatch::class ], compatiblePackages = [ CompatiblePackage( @@ -32,16 +32,20 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object CrowdfundingBoxPatch : BytecodePatch( - setOf(CrowdfundingBoxFingerprint), + setOf(CrowdfundingBoxFingerprint) ) { private const val INTEGRATIONS_METHOD_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/HideCrowdfundingBoxPatch;->hideCrowdfundingBox(Landroid/view/View;)V" diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsPatch.kt index 05c496b6b..aecd7cf12 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsPatch.kt @@ -1,5 +1,6 @@ package app.revanced.patches.youtube.layout.hide.endscreencards +import app.revanced.util.exception import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction @@ -11,7 +12,6 @@ import app.revanced.patches.youtube.layout.hide.endscreencards.fingerprints.Layo import app.revanced.patches.youtube.layout.hide.endscreencards.fingerprints.LayoutIconFingerprint import app.revanced.patches.youtube.layout.hide.endscreencards.fingerprints.LayoutVideoFingerprint import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch -import app.revanced.util.exception import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c @Patch( @@ -19,7 +19,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c description = "Adds an option to hide suggested video cards at the end of videos.", dependencies = [ IntegrationsPatch::class, - HideEndscreenCardsResourcePatch::class, + HideEndscreenCardsResourcePatch::class ], compatiblePackages = [ CompatiblePackage( @@ -35,12 +35,16 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object HideEndscreenCardsPatch : BytecodePatch( @@ -48,7 +52,7 @@ object HideEndscreenCardsPatch : BytecodePatch( LayoutCircleFingerprint, LayoutIconFingerprint, LayoutVideoFingerprint, - ), + ) ) { override fun execute(context: BytecodeContext) { fun MethodFingerprint.injectHideCall() { @@ -59,7 +63,7 @@ object HideEndscreenCardsPatch : BytecodePatch( addInstruction( insertIndex, - "invoke-static { v$viewRegister }, Lapp/revanced/integrations/youtube/patches/HideEndscreenCardsPatch;->hideEndscreen(Landroid/view/View;)V", + "invoke-static { v$viewRegister }, Lapp/revanced/integrations/youtube/patches/HideEndscreenCardsPatch;->hideEndscreen(Landroid/view/View;)V" ) } } @@ -67,7 +71,7 @@ object HideEndscreenCardsPatch : BytecodePatch( listOf( LayoutCircleFingerprint, LayoutIconFingerprint, - LayoutVideoFingerprint, + LayoutVideoFingerprint ).forEach(MethodFingerprint::injectHideCall) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/HideFilterBarPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/HideFilterBarPatch.kt index 59db28177..0a836aa5a 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/HideFilterBarPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/filterbar/HideFilterBarPatch.kt @@ -1,5 +1,6 @@ package app.revanced.patches.youtube.layout.hide.filterbar +import app.revanced.util.exception import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction @@ -10,7 +11,6 @@ import app.revanced.patcher.patch.annotation.Patch 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 app.revanced.util.exception import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction @@ -32,20 +32,24 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object HideFilterBarPatch : BytecodePatch( setOf( RelatedChipCloudFingerprint, SearchResultsChipBarFingerprint, - FilterBarHeightFingerprint, - ), + FilterBarHeightFingerprint + ) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/HideFilterBarPatch;" @@ -60,7 +64,7 @@ object HideFilterBarPatch : BytecodePatch( RelatedChipCloudFingerprint.patch(1) { register -> "invoke-static { v$register }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->hideInRelatedVideos(Landroid/view/View;)V" + "$INTEGRATIONS_CLASS_DESCRIPTOR->hideInRelatedVideos(Landroid/view/View;)V" } SearchResultsChipBarFingerprint.patch(-1, -2) { register -> @@ -82,7 +86,7 @@ object HideFilterBarPatch : BytecodePatch( private fun MethodFingerprint.patch( insertIndexOffset: Int = 0, hookRegisterOffset: Int = 0, - instructions: (Int) -> String, + instructions: (Int) -> String ) = result?.let { it.mutableMethod.apply { diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/HideFloatingMicrophoneButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/HideFloatingMicrophoneButtonPatch.kt index afd47abe8..1b4606c4e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/HideFloatingMicrophoneButtonPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/floatingmicrophone/HideFloatingMicrophoneButtonPatch.kt @@ -1,5 +1,6 @@ package app.revanced.patches.youtube.layout.hide.floatingmicrophone +import app.revanced.util.exception import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction @@ -7,7 +8,6 @@ import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.youtube.layout.hide.floatingmicrophone.fingerprints.ShowFloatingMicrophoneButtonFingerprint -import app.revanced.util.exception import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction @Patch( @@ -28,16 +28,20 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object HideFloatingMicrophoneButtonPatch : BytecodePatch( - setOf(ShowFloatingMicrophoneButtonFingerprint), + setOf(ShowFloatingMicrophoneButtonFingerprint) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/HideFloatingMicrophoneButtonPatch;" @@ -54,7 +58,7 @@ object HideFloatingMicrophoneButtonPatch : BytecodePatch( """ invoke-static {v$showButtonRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->hideFloatingMicrophoneButton(Z)Z move-result v$showButtonRegister - """, + """ ) } } ?: throw ShowFloatingMicrophoneButtonFingerprint.exception diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/fullscreenambientmode/DisableFullscreenAmbientModePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/fullscreenambientmode/DisableFullscreenAmbientModePatch.kt index 1e34bd21a..0a4ea85b0 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/fullscreenambientmode/DisableFullscreenAmbientModePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/fullscreenambientmode/DisableFullscreenAmbientModePatch.kt @@ -18,8 +18,7 @@ import app.revanced.util.exception dependencies = [SettingsPatch::class, IntegrationsPatch::class, AddResourcesPatch::class], compatiblePackages = [ CompatiblePackage( - "com.google.android.youtube", - [ + "com.google.android.youtube", [ "18.37.36", "18.38.44", "18.43.45", @@ -29,16 +28,20 @@ import app.revanced.util.exception "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object DisableFullscreenAmbientModePatch : BytecodePatch( - setOf(InitializeAmbientModeFingerprint), + setOf(InitializeAmbientModeFingerprint) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/DisableFullscreenAmbientModePatch;" @@ -47,7 +50,7 @@ object DisableFullscreenAmbientModePatch : BytecodePatch( AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.PLAYER.addPreferences( - SwitchPreference("revanced_disable_fullscreen_ambient_mode"), + SwitchPreference("revanced_disable_fullscreen_ambient_mode") ) InitializeAmbientModeFingerprint.result?.let { @@ -57,7 +60,7 @@ object DisableFullscreenAmbientModePatch : BytecodePatch( addInstruction( moveIsEnabledIndex, "invoke-static { }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->enableFullScreenAmbientMode()Z", + "$INTEGRATIONS_CLASS_DESCRIPTOR->enableFullScreenAmbientMode()Z" ) } } ?: throw InitializeAmbientModeFingerprint.exception diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt index f72d80a32..5a7428d7e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt @@ -12,6 +12,7 @@ import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.all.misc.resources.AddResourcesPatch import app.revanced.patches.shared.misc.settings.preference.InputType +import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting import app.revanced.patches.shared.misc.settings.preference.SwitchPreference @@ -20,8 +21,10 @@ import app.revanced.patches.youtube.layout.hide.general.fingerprints.ParseElemen import app.revanced.patches.youtube.layout.hide.general.fingerprints.PlayerOverlayFingerprint import app.revanced.patches.youtube.layout.hide.general.fingerprints.ShowWatermarkFingerprint import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch +import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch +import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch import app.revanced.patches.youtube.misc.settings.SettingsPatch -import app.revanced.util.exception +import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction @@ -33,6 +36,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction LithoFilterPatch::class, SettingsPatch::class, AddResourcesPatch::class, + NavigationBarHookPatch::class, + PlayerTypeHookPatch::class // Used by Keyword Content filter. ], compatiblePackages = [ CompatiblePackage( @@ -48,9 +53,13 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37", ], ), ], @@ -65,6 +74,8 @@ object HideLayoutComponentsPatch : BytecodePatch( "Lapp/revanced/integrations/youtube/patches/components/DescriptionComponentsFilter;" private const val CUSTOM_FILTER_CLASS_NAME = "Lapp/revanced/integrations/youtube/patches/components/CustomFilter;" + private const val KEYWORD_FILTER_CLASS_NAME = + "Lapp/revanced/integrations/youtube/patches/components/KeywordContentFilter;" override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) @@ -90,6 +101,7 @@ object HideLayoutComponentsPatch : BytecodePatch( SwitchPreference("revanced_hide_emergency_box"), SwitchPreference("revanced_hide_expandable_chip"), SwitchPreference("revanced_hide_info_panels"), + SwitchPreference("revanced_hide_join_membership_button"), SwitchPreference("revanced_hide_medical_panels"), SwitchPreference("revanced_hide_quick_actions"), SwitchPreference("revanced_hide_related_videos"), @@ -104,7 +116,6 @@ object HideLayoutComponentsPatch : BytecodePatch( SwitchPreference("revanced_hide_feed_survey"), SwitchPreference("revanced_hide_for_you_shelf"), SwitchPreference("revanced_hide_image_shelf"), - SwitchPreference("revanced_hide_join_membership_button"), SwitchPreference("revanced_hide_latest_posts_ads"), SwitchPreference("revanced_hide_mix_playlists"), SwitchPreference("revanced_hide_movies_section"), @@ -113,6 +124,20 @@ object HideLayoutComponentsPatch : BytecodePatch( SwitchPreference("revanced_hide_search_result_shelf_header"), ) + SettingsPatch.PreferenceScreen.FEED.addPreferences( + PreferenceScreen( + key = "revanced_hide_keyword_content_screen", + sorting = Sorting.UNSORTED, + preferences = setOf( + SwitchPreference("revanced_hide_keyword_content_home"), + SwitchPreference("revanced_hide_keyword_content_subscriptions"), + SwitchPreference("revanced_hide_keyword_content_search"), + TextPreference("revanced_hide_keyword_content_phrases", inputType = InputType.TEXT_MULTI_LINE), + NonInteractivePreference("revanced_hide_keyword_content_about") + ) + ) + ) + SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences( SwitchPreference("revanced_hide_gray_separator"), PreferenceScreen( @@ -132,19 +157,19 @@ object HideLayoutComponentsPatch : BytecodePatch( LithoFilterPatch.addFilter(LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR) LithoFilterPatch.addFilter(DESCRIPTION_COMPONENTS_FILTER_CLASS_NAME) + LithoFilterPatch.addFilter(KEYWORD_FILTER_CLASS_NAME) LithoFilterPatch.addFilter(CUSTOM_FILTER_CLASS_NAME) // region Mix playlists - ParseElementFromBufferFingerprint.result?.let { result -> - val returnEmptyComponentInstruction = - result.mutableMethod.getInstructions().last { it.opcode == Opcode.INVOKE_STATIC } + ParseElementFromBufferFingerprint.resultOrThrow().let { result -> + val consumeByteBufferIndex = result.scanResult.patternScanResult!!.startIndex result.mutableMethod.apply { - val consumeByteBufferIndex = result.scanResult.patternScanResult!!.startIndex val conversionContextRegister = getInstruction(consumeByteBufferIndex - 2).registerA val byteBufferRegister = getInstruction(consumeByteBufferIndex).registerD + val returnEmptyComponentInstruction = getInstructions().last { it.opcode == Opcode.INVOKE_STATIC } addInstructionsWithLabels( consumeByteBufferIndex, @@ -156,15 +181,15 @@ object HideLayoutComponentsPatch : BytecodePatch( ExternalLabel("return_empty_component", returnEmptyComponentInstruction), ) } - } ?: throw ParseElementFromBufferFingerprint.exception + } // endregion // region Watermark (legacy code for old versions of YouTube) ShowWatermarkFingerprint.also { - it.resolve(context, PlayerOverlayFingerprint.result?.classDef ?: throw PlayerOverlayFingerprint.exception) - }.result?.mutableMethod?.apply { + it.resolve(context, PlayerOverlayFingerprint.resultOrThrow().classDef) + }.resultOrThrow().mutableMethod.apply { val index = implementation!!.instructions.size - 5 removeInstruction(index) @@ -175,7 +200,7 @@ object HideLayoutComponentsPatch : BytecodePatch( move-result p2 """, ) - } ?: throw ShowWatermarkFingerprint.exception + } // endregion } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt index 604707b06..7cb8d8658 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt @@ -23,7 +23,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction dependencies = [ IntegrationsPatch::class, LithoFilterPatch::class, - HideInfocardsResourcePatch::class, + HideInfocardsResourcePatch::class ], compatiblePackages = [ CompatiblePackage( @@ -39,19 +39,23 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object HideInfoCardsPatch : BytecodePatch( setOf( InfocardsIncognitoParentFingerprint, InfocardsMethodCallFingerprint, - ), + ) ) { private const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/components/HideInfoCardsFilterPatch;" @@ -62,14 +66,14 @@ object HideInfoCardsPatch : BytecodePatch( }.result!!.mutableMethod.apply { val invokeInstructionIndex = implementation!!.instructions.indexOfFirst { it.opcode.ordinal == Opcode.INVOKE_VIRTUAL.ordinal && - ((it as ReferenceInstruction).reference.toString() == "Landroid/view/View;->setVisibility(I)V") + ((it as ReferenceInstruction).reference.toString() == "Landroid/view/View;->setVisibility(I)V") } - addInstruction( - invokeInstructionIndex, - "invoke-static {v${getInstruction(invokeInstructionIndex).registerC}}," + - " Lapp/revanced/integrations/youtube/patches/HideInfoCardsPatch;->hideInfoCardsIncognito(Landroid/view/View;)V", - ) + addInstruction( + invokeInstructionIndex, + "invoke-static {v${getInstruction(invokeInstructionIndex).registerC}}," + + " Lapp/revanced/integrations/youtube/patches/HideInfoCardsPatch;->hideInfoCardsIncognito(Landroid/view/View;)V" + ) } with(InfocardsMethodCallFingerprint.result!!) { @@ -86,13 +90,12 @@ object HideInfoCardsPatch : BytecodePatch( if-nez v$toggleRegister, :hide_info_cards """, ExternalLabel( - "hide_info_cards", - hideInfoCardsCallMethod.getInstruction(invokeInterfaceIndex + 1), - ), + "hide_info_cards", hideInfoCardsCallMethod.getInstruction(invokeInterfaceIndex + 1) + ) ) } // Info cards can also appear as litho components. LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR) } -} +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/HideLoadMoreButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/HideLoadMoreButtonPatch.kt index c37f64ff4..91948d7f2 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/HideLoadMoreButtonPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/loadmorebutton/HideLoadMoreButtonPatch.kt @@ -1,5 +1,6 @@ package app.revanced.patches.youtube.layout.hide.loadmorebutton +import app.revanced.util.exception import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction @@ -7,7 +8,6 @@ import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.youtube.layout.hide.loadmorebutton.fingerprints.HideLoadMoreButtonFingerprint -import app.revanced.util.exception import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @Patch( @@ -28,16 +28,20 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object HideLoadMoreButtonPatch : BytecodePatch( - setOf(HideLoadMoreButtonFingerprint), + setOf(HideLoadMoreButtonFingerprint) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/HideLoadMoreButtonPatch;" @@ -53,7 +57,7 @@ object HideLoadMoreButtonPatch : BytecodePatch( addInstruction( insertIndex, "invoke-static { v$viewRegister }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->hideLoadMoreButton(Landroid/view/View;)V", + "$INTEGRATIONS_CLASS_DESCRIPTOR->hideLoadMoreButton(Landroid/view/View;)V" ) } } ?: throw HideLoadMoreButtonFingerprint.exception diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/flyoutmenupanel/HidePlayerFlyoutMenuPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/flyoutmenupanel/HidePlayerFlyoutMenuPatch.kt index ba7d78842..00d9dfe61 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/flyoutmenupanel/HidePlayerFlyoutMenuPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/flyoutmenupanel/HidePlayerFlyoutMenuPatch.kt @@ -18,12 +18,11 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch LithoFilterPatch::class, PlayerTypeHookPatch::class, SettingsPatch::class, - AddResourcesPatch::class, + AddResourcesPatch::class ], compatiblePackages = [ CompatiblePackage( - "com.google.android.youtube", - [ + "com.google.android.youtube", [ "18.32.39", "18.37.36", "18.38.44", @@ -34,12 +33,16 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object HidePlayerFlyoutMenuPatch : ResourcePatch() { @@ -66,7 +69,7 @@ object HidePlayerFlyoutMenuPatch : ResourcePatch() { SwitchPreference("${KEY}_audio_track"), SwitchPreference("${KEY}_watch_in_vr"), ), - ), + ) ) LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR) diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/rollingnumber/DisableRollingNumberAnimationPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/rollingnumber/DisableRollingNumberAnimationPatch.kt index 24fec7a09..5758d813f 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/rollingnumber/DisableRollingNumberAnimationPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/rollingnumber/DisableRollingNumberAnimationPatch.kt @@ -22,8 +22,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class], compatiblePackages = [ CompatiblePackage( - "com.google.android.youtube", - [ + "com.google.android.youtube", [ "18.43.45", "18.44.41", "18.45.43", @@ -31,18 +30,22 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object DisableRollingNumberAnimationPatch : BytecodePatch( setOf( - RollingNumberTextViewAnimationUpdateFingerprint, - ), + RollingNumberTextViewAnimationUpdateFingerprint + ) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/DisableRollingNumberAnimationsPatch;" @@ -51,7 +54,7 @@ object DisableRollingNumberAnimationPatch : BytecodePatch( AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.PLAYER.addPreferences( - SwitchPreference("revanced_disable_rolling_number_animations"), + SwitchPreference("revanced_disable_rolling_number_animations") ) // Animations are disabled by preventing an Image from being applied to the text span, @@ -75,7 +78,7 @@ object DisableRollingNumberAnimationPatch : BytecodePatch( move-result v$freeRegister if-nez v$freeRegister, :disable_animations """, - ExternalLabel("disable_animations", getInstruction(blockEndIndex)), + ExternalLabel("disable_animations", getInstruction(blockEndIndex)) ) } } ?: throw RollingNumberTextViewAnimationUpdateFingerprint.exception diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/HideSeekbarPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/HideSeekbarPatch.kt index d5de59f47..8e8434af9 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/HideSeekbarPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/seekbar/HideSeekbarPatch.kt @@ -20,12 +20,11 @@ import app.revanced.patches.youtube.shared.fingerprints.SeekbarOnDrawFingerprint IntegrationsPatch::class, SettingsPatch::class, SeekbarColorBytecodePatch::class, - AddResourcesPatch::class, + AddResourcesPatch::class ], compatiblePackages = [ CompatiblePackage( - "com.google.android.youtube", - [ + "com.google.android.youtube", [ "18.32.39", "18.37.36", "18.38.44", @@ -36,23 +35,27 @@ import app.revanced.patches.youtube.shared.fingerprints.SeekbarOnDrawFingerprint "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object HideSeekbarPatch : BytecodePatch( - setOf(SeekbarFingerprint), + setOf(SeekbarFingerprint) ) { override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.SEEKBAR.addPreferences( SwitchPreference("revanced_hide_seekbar"), - SwitchPreference("revanced_hide_seekbar_thumbnail"), + SwitchPreference("revanced_hide_seekbar_thumbnail") ) SeekbarFingerprint.result!!.let { @@ -67,7 +70,7 @@ object HideSeekbarPatch : BytecodePatch( return-void :hide_seekbar nop - """, + """ ) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt index cc0542bc7..e65eced6c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt @@ -1,5 +1,8 @@ package app.revanced.patches.youtube.layout.hide.shorts +import app.revanced.util.exception +import app.revanced.util.findIndexForIdResource +import app.revanced.util.injectHideViewCall import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction @@ -8,18 +11,11 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.shared.misc.mapping.ResourceMappingPatch -import app.revanced.patches.youtube.layout.hide.shorts.fingerprints.BottomNavigationBarFingerprint -import app.revanced.patches.youtube.layout.hide.shorts.fingerprints.CreateShortsButtonsFingerprint -import app.revanced.patches.youtube.layout.hide.shorts.fingerprints.ReelConstructorFingerprint -import app.revanced.patches.youtube.layout.hide.shorts.fingerprints.RenderBottomNavigationBarFingerprint -import app.revanced.patches.youtube.layout.hide.shorts.fingerprints.RenderBottomNavigationBarParentFingerprint -import app.revanced.patches.youtube.layout.hide.shorts.fingerprints.SetPivotBarVisibilityFingerprint -import app.revanced.patches.youtube.layout.hide.shorts.fingerprints.SetPivotBarVisibilityParentFingerprint +import app.revanced.patches.youtube.layout.hide.shorts.fingerprints.* import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch -import app.revanced.util.exception -import app.revanced.util.findIndexForIdResource -import app.revanced.util.injectHideViewCall +import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch +import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction @@ -31,12 +27,13 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction IntegrationsPatch::class, LithoFilterPatch::class, HideShortsComponentsResourcePatch::class, - ResourceMappingPatch::class + ResourceMappingPatch::class, + NavigationBarHookPatch::class, + PlayerTypeHookPatch::class ], compatiblePackages = [ CompatiblePackage( - "com.google.android.youtube", - [ + "com.google.android.youtube", [ "18.32.39", "18.37.36", "18.38.44", @@ -47,9 +44,13 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37" + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" ] ) ] @@ -94,6 +95,7 @@ object HideShortsComponentsPatch : BytecodePatch( ShortsButtons.entries.forEach { button -> button.injectHideCall(it.mutableMethod) } } ?: throw CreateShortsButtonsFingerprint.exception + // endregion // region Hide the Shorts buttons in newer versions of YouTube. @@ -106,9 +108,8 @@ object HideShortsComponentsPatch : BytecodePatch( // Hook to get the pivotBar view. SetPivotBarVisibilityParentFingerprint.result?.let { - if (!SetPivotBarVisibilityFingerprint.resolve(context, it.classDef)) { + if (!SetPivotBarVisibilityFingerprint.resolve(context, it.classDef)) throw SetPivotBarVisibilityFingerprint.exception - } SetPivotBarVisibilityFingerprint.result!!.let { result -> result.mutableMethod.apply { @@ -117,7 +118,7 @@ object HideShortsComponentsPatch : BytecodePatch( addInstruction( insertIndex, "sput-object v$viewRegister, $FILTER_CLASS_DESCRIPTOR->pivotBar:" + - "Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;" + "Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;" ) } } @@ -125,9 +126,8 @@ object HideShortsComponentsPatch : BytecodePatch( // Hook to hide the navigation bar when Shorts are being played. RenderBottomNavigationBarParentFingerprint.result?.let { - if (!RenderBottomNavigationBarFingerprint.resolve(context, it.classDef)) { + if (!RenderBottomNavigationBarFingerprint.resolve(context, it.classDef)) throw RenderBottomNavigationBarFingerprint.exception - } RenderBottomNavigationBarFingerprint.result!!.mutableMethod.apply { addInstruction(0, "invoke-static { }, $FILTER_CLASS_DESCRIPTOR->hideNavigationBar()V") @@ -144,7 +144,7 @@ object HideShortsComponentsPatch : BytecodePatch( addInstruction( insertIndex, "invoke-static { v$viewRegister }, $FILTER_CLASS_DESCRIPTOR->" + - "hideNavigationBar(Landroid/view/View;)Landroid/view/View;" + "hideNavigationBar(Landroid/view/View;)Landroid/view/View;" ) } } ?: throw BottomNavigationBarFingerprint.exception @@ -152,11 +152,11 @@ object HideShortsComponentsPatch : BytecodePatch( // endregion } + 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") - ; + SHARE("reel_dyn_share", "hideShortsShareButton"); fun injectHideCall(method: MutableMethod) { val referencedIndex = method.findIndexForIdResource(resourceName) diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsResourcePatch.kt index 227cc9429..8593cd056 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsResourcePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsResourcePatch.kt @@ -17,17 +17,32 @@ object HideShortsComponentsResourcePatch : ResourcePatch() { AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.SHORTS.addPreferences( - SwitchPreference("revanced_hide_shorts"), + SwitchPreference("revanced_hide_shorts_home"), + SwitchPreference("revanced_hide_shorts_subscriptions"), + SwitchPreference("revanced_hide_shorts_search"), + + // Shorts player components. + // Ideally each group should be ordered similar to how they appear in the UI + // since this Setting menu currently uses the ordering used here. + + // Vertical row of buttons on right side of the screen. + SwitchPreference("revanced_hide_shorts_like_button"), + SwitchPreference("revanced_hide_shorts_dislike_button"), + SwitchPreference("revanced_hide_shorts_comments_button"), + SwitchPreference("revanced_hide_shorts_share_button"), + SwitchPreference("revanced_hide_shorts_remix_button"), + SwitchPreference("revanced_hide_shorts_sound_button"), + + // Everything else. + SwitchPreference("revanced_hide_shorts_thanks_button"), SwitchPreference("revanced_hide_shorts_join_button"), SwitchPreference("revanced_hide_shorts_subscribe_button"), SwitchPreference("revanced_hide_shorts_subscribe_button_paused"), - SwitchPreference("revanced_hide_shorts_thanks_button"), - SwitchPreference("revanced_hide_shorts_comments_button"), - SwitchPreference("revanced_hide_shorts_remix_button"), - SwitchPreference("revanced_hide_shorts_share_button"), - SwitchPreference("revanced_hide_shorts_info_panel"), SwitchPreference("revanced_hide_shorts_channel_bar"), - SwitchPreference("revanced_hide_shorts_sound_button"), + SwitchPreference("revanced_hide_shorts_info_panel"), + SwitchPreference("revanced_hide_shorts_full_video_link_label"), + SwitchPreference("revanced_hide_shorts_video_title"), + SwitchPreference("revanced_hide_shorts_sound_metadata_label"), SwitchPreference("revanced_hide_shorts_navigation_bar"), ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/suggestedvideoendscreen/DisableSuggestedVideoEndScreenPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/suggestedvideoendscreen/DisableSuggestedVideoEndScreenPatch.kt index 062aacc6f..c939e786d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/suggestedvideoendscreen/DisableSuggestedVideoEndScreenPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/suggestedvideoendscreen/DisableSuggestedVideoEndScreenPatch.kt @@ -1,5 +1,6 @@ package app.revanced.patches.youtube.layout.hide.suggestedvideoendscreen +import app.revanced.util.exception import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction @@ -8,7 +9,6 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.youtube.layout.hide.suggestedvideoendscreen.fingerprints.CreateEndScreenViewFingerprint import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch -import app.revanced.util.exception import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @Patch( @@ -17,8 +17,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction dependencies = [IntegrationsPatch::class, DisableSuggestedVideoEndScreenResourcePatch::class], compatiblePackages = [ CompatiblePackage( - "com.google.android.youtube", - [ + "com.google.android.youtube", [ "18.37.36", "18.38.44", "18.43.45", @@ -28,16 +27,20 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object DisableSuggestedVideoEndScreenPatch : BytecodePatch( - setOf(CreateEndScreenViewFingerprint), + setOf(CreateEndScreenViewFingerprint) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/DisableSuggestedVideoEndScreenPatch;" @@ -51,7 +54,7 @@ object DisableSuggestedVideoEndScreenPatch : BytecodePatch( addInstruction( addOnClickEventListenerIndex + 1, "invoke-static {v$viewRegister}, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->closeEndScreen(Landroid/widget/ImageView;)V", + "$INTEGRATIONS_CLASS_DESCRIPTOR->closeEndScreen(Landroid/widget/ImageView;)V" ) } } ?: throw CreateEndScreenViewFingerprint.exception diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/HideTimestampPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/HideTimestampPatch.kt index 58d4f52ae..a3c731ef1 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/HideTimestampPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/time/HideTimestampPatch.kt @@ -18,8 +18,7 @@ import app.revanced.util.exception dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class], compatiblePackages = [ CompatiblePackage( - "com.google.android.youtube", - [ + "com.google.android.youtube", [ "18.37.36", "18.38.44", "18.43.45", @@ -29,35 +28,39 @@ import app.revanced.util.exception "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object HideTimestampPatch : BytecodePatch( - setOf(TimeCounterFingerprint), + setOf(TimeCounterFingerprint) ) { override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.SEEKBAR.addPreferences( - SwitchPreference("revanced_hide_timestamp"), + SwitchPreference("revanced_hide_timestamp") ) TimeCounterFingerprint.result?.apply { mutableMethod.addInstructionsWithLabels( - 0, - """ + 0, + """ invoke-static { }, Lapp/revanced/integrations/youtube/patches/HideTimestampPatch;->hideTimestamp()Z move-result v0 if-eqz v0, :hide_time return-void :hide_time nop - """, + """ ) } ?: throw TimeCounterFingerprint.exception } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/PlayerPopupPanelsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/PlayerPopupPanelsPatch.kt index 56bee2faa..58fade4e0 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/PlayerPopupPanelsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/panels/popup/PlayerPopupPanelsPatch.kt @@ -18,8 +18,7 @@ import app.revanced.util.exception dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class], compatiblePackages = [ CompatiblePackage( - "com.google.android.youtube", - [ + "com.google.android.youtube", [ "18.32.39", "18.37.36", "18.38.44", @@ -30,22 +29,26 @@ import app.revanced.util.exception "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object PlayerPopupPanelsPatch : BytecodePatch( - setOf(EngagementPanelControllerFingerprint), + setOf(EngagementPanelControllerFingerprint) ) { override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.PLAYER.addPreferences( - SwitchPreference("revanced_hide_player_popup_panels"), + SwitchPreference("revanced_hide_player_popup_panels") ) val engagementPanelControllerMethod = EngagementPanelControllerFingerprint @@ -62,7 +65,7 @@ object PlayerPopupPanelsPatch : BytecodePatch( return-object v0 :player_popup_panels nop - """, + """ ) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/PlayerControlsBackgroundPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/PlayerControlsBackgroundPatch.kt index 9dcbc49dc..d5e1893a2 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/PlayerControlsBackgroundPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/player/background/PlayerControlsBackgroundPatch.kt @@ -24,9 +24,13 @@ import org.w3c.dom.Element "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" ], ), ], diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt index a8de7bdef..783474eb3 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt @@ -32,6 +32,7 @@ import app.revanced.patches.youtube.video.videoid.VideoIdPatch import app.revanced.util.exception import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstruction +import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @@ -53,17 +54,20 @@ import com.android.tools.smali.dexlib2.iface.reference.TypeReference ], compatiblePackages = [ CompatiblePackage( - "com.google.android.youtube", - [ + "com.google.android.youtube", [ "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object ReturnYouTubeDislikePatch : BytecodePatch( @@ -80,8 +84,8 @@ object ReturnYouTubeDislikePatch : BytecodePatch( RollingNumberMeasureStaticLabelParentFingerprint, RollingNumberMeasureAnimatedTextFingerprint, RollingNumberTextViewFingerprint, - RollingNumberTextViewAnimationUpdateFingerprint, - ), + RollingNumberTextViewAnimationUpdateFingerprint + ) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/ReturnYouTubeDislikePatch;" @@ -89,8 +93,6 @@ object ReturnYouTubeDislikePatch : BytecodePatch( private const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/components/ReturnYouTubeDislikeFilterPatch;" - private fun MethodFingerprint.resultOrThrow() = result ?: throw exception - override fun execute(context: BytecodeContext) { // region Inject newVideoLoaded event handler to update dislikes when a new video is loaded. @@ -106,7 +108,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch( listOf( LikeFingerprint.toPatch(Vote.LIKE), DislikeFingerprint.toPatch(Vote.DISLIKE), - RemoveLikeFingerprint.toPatch(Vote.REMOVE_LIKE), + RemoveLikeFingerprint.toPatch(Vote.REMOVE_LIKE) ).forEach { (fingerprint, vote) -> fingerprint.result?.mutableMethod?.apply { addInstructions( @@ -114,7 +116,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch( """ const/4 v0, ${vote.value} invoke-static {v0}, $INTEGRATIONS_CLASS_DESCRIPTOR->sendVote(I)V - """, + """ ) } ?: throw fingerprint.exception } @@ -140,7 +142,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch( val textDataClassType = TextComponentDataFingerprint.resultOrThrow().classDef.type val insertIndex = indexOfFirstInstruction { opcode == Opcode.NEW_INSTANCE && - getReference()?.type == textDataClassType + getReference()?.type == textDataClassType } if (insertIndex < 0) throw PatchException("Could not find data creation instruction") val tempRegister = getInstruction(insertIndex).registerA @@ -153,7 +155,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch( .subList(insertIndex, insertIndex + 20) .find { it.opcode == Opcode.IPUT_OBJECT && - it.getReference()?.type == "Ljava/lang/CharSequence;" + it.getReference()?.type == "Ljava/lang/CharSequence;" } ?: throw PatchException("Could not find put object instruction") val charSequenceRegister = (putFieldInstruction as TwoRegisterInstruction).registerA @@ -165,7 +167,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch( iget-object v$tempRegister, v$tempRegister, $conversionContextField invoke-static {v$tempRegister, v$charSequenceRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onLithoTextLoaded(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence; move-result-object v$charSequenceRegister - """, + """ ) } } ?: throw TextComponentConstructorFingerprint.exception @@ -205,7 +207,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch( :is_like :ryd_disabled nop - """, + """ ) } } ?: throw ShortsTextViewFingerprint.exception @@ -233,13 +235,14 @@ object ReturnYouTubeDislikePatch : BytecodePatch( addInstruction( startIndex + 4, - "invoke-static {v$resourceIdentifierRegister, v$textViewRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->setOldUILayoutDislikes(ILandroid/widget/TextView;)V", + "invoke-static {v$resourceIdentifierRegister, v$textViewRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->setOldUILayoutDislikes(ILandroid/widget/TextView;)V" ) } } ?: throw DislikesOldLayoutTextViewFingerprint.exception // endregion + // region Hook rolling numbers. // Do this last to allow patching old unsupported versions (if the user really wants), @@ -270,7 +273,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch( invoke-static {v$conversionContextRegister, v$freeRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onRollingNumberLoaded(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String; move-result-object v$freeRegister iput-object v$freeRegister, v$charSequenceInstanceRegister, $charSequenceFieldReference - """, + """ ) } } ?: throw RollingNumberSetterFingerprint.exception @@ -290,7 +293,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch( """ invoke-static {p1, v$measuredTextWidthRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F move-result v$measuredTextWidthRegister - """, + """ ) } } ?: throw RollingNumberMeasureAnimatedTextFingerprint.exception @@ -308,7 +311,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch( """ move-result v$freeRegister invoke-static {p1, v$freeRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F - """, + """ ) } } ?: throw RollingNumberMeasureStaticLabelFingerprint.exception @@ -327,7 +330,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch( arrayOf( initiallyCreatedTextViewMethod, - realTimeUpdateTextViewMethod, + realTimeUpdateTextViewMethod ).forEach { insertMethod -> insertMethod.apply { val setTextIndex = indexOfFirstInstruction { @@ -344,13 +347,14 @@ object ReturnYouTubeDislikePatch : BytecodePatch( """ invoke-static {v$textViewRegister, v$textSpanRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->updateRollingNumber(Landroid/widget/TextView;Ljava/lang/CharSequence;)Ljava/lang/CharSequence; move-result-object v$textSpanRegister - """, + """ ) } } } ?: throw RollingNumberTextViewFingerprint.exception // endregion + } private fun MethodFingerprint.toPatch(voteKind: Vote) = VotePatch(this, voteKind) @@ -358,6 +362,6 @@ object ReturnYouTubeDislikePatch : BytecodePatch( private enum class Vote(val value: Int) { LIKE(1), DISLIKE(-1), - REMOVE_LIKE(0), + REMOVE_LIKE(0) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/WideSearchbarPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/WideSearchbarPatch.kt index adffd1c08..3cd258b78 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/WideSearchbarPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/searchbar/WideSearchbarPatch.kt @@ -23,8 +23,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class], compatiblePackages = [ CompatiblePackage( - "com.google.android.youtube", - [ + "com.google.android.youtube", [ "18.32.39", "18.37.36", "18.38.44", @@ -34,19 +33,23 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object WideSearchbarPatch : BytecodePatch( setOf( SetWordmarkHeaderFingerprint, - CreateSearchSuggestionsFingerprint, - ), + CreateSearchSuggestionsFingerprint + ) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = @@ -56,7 +59,7 @@ object WideSearchbarPatch : BytecodePatch( AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.FEED.addPreferences( - SwitchPreference("revanced_wide_searchbar"), + SwitchPreference("revanced_wide_searchbar") ) val result = CreateSearchSuggestionsFingerprint.result ?: throw CreateSearchSuggestionsFingerprint.exception @@ -64,7 +67,7 @@ object WideSearchbarPatch : BytecodePatch( // patch methods mapOf( SetWordmarkHeaderFingerprint to 1, - CreateSearchSuggestionsFingerprint to result.scanResult.patternScanResult!!.startIndex, + CreateSearchSuggestionsFingerprint to result.scanResult.patternScanResult!!.startIndex ).forEach { (fingerprint, callIndex) -> context.walkMutable(callIndex, fingerprint).injectSearchBarHook() } @@ -82,6 +85,7 @@ object WideSearchbarPatch : BytecodePatch( toMethodWalker(it.method).nextMethod(index, true).getMethod() as MutableMethod } ?: throw fromFingerprint.exception + /** * Injects instructions required for certain methods. */ @@ -94,7 +98,7 @@ object WideSearchbarPatch : BytecodePatch( """ invoke-static {v$insertRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->enableWideSearchbar(Z)Z move-result v$insertRegister - """, + """ ) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/RestoreOldSeekbarThumbnailsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/RestoreOldSeekbarThumbnailsPatch.kt index 8ffbbdbb8..77de2e752 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/RestoreOldSeekbarThumbnailsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/RestoreOldSeekbarThumbnailsPatch.kt @@ -19,8 +19,7 @@ import app.revanced.util.exception dependencies = [IntegrationsPatch::class, AddResourcesPatch::class], compatiblePackages = [ CompatiblePackage( - "com.google.android.youtube", - [ + "com.google.android.youtube", [ "18.37.36", "18.38.44", "18.43.45", @@ -30,16 +29,20 @@ import app.revanced.util.exception "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object RestoreOldSeekbarThumbnailsPatch : BytecodePatch( - setOf(FullscreenSeekbarThumbnailsFingerprint), + setOf(FullscreenSeekbarThumbnailsFingerprint) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/RestoreOldSeekbarThumbnailsPatch;" @@ -48,7 +51,7 @@ object RestoreOldSeekbarThumbnailsPatch : BytecodePatch( AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.SEEKBAR.addPreferences( - SwitchPreference("revanced_restore_old_seekbar_thumbnails"), + SwitchPreference("revanced_restore_old_seekbar_thumbnails") ) FullscreenSeekbarThumbnailsFingerprint.result?.mutableMethod?.apply { @@ -56,7 +59,7 @@ object RestoreOldSeekbarThumbnailsPatch : BytecodePatch( addInstruction( moveResultIndex, - "invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->useFullscreenSeekbarThumbnails()Z", + "invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->useFullscreenSeekbarThumbnails()Z" ) } ?: throw FullscreenSeekbarThumbnailsFingerprint.exception } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockBytecodePatch.kt index 18b2140da..52ab535e8 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockBytecodePatch.kt @@ -1,5 +1,6 @@ package app.revanced.patches.youtube.layout.sponsorblock +import app.revanced.util.exception import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstructions @@ -24,7 +25,6 @@ import app.revanced.patches.youtube.shared.fingerprints.SeekbarFingerprint import app.revanced.patches.youtube.shared.fingerprints.SeekbarOnDrawFingerprint import app.revanced.patches.youtube.video.information.VideoInformationPatch import app.revanced.patches.youtube.video.videoid.VideoIdPatch -import app.revanced.util.exception import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.* import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c @@ -37,17 +37,20 @@ import com.android.tools.smali.dexlib2.iface.reference.StringReference description = "Adds options to enable and configure SponsorBlock, which can skip undesired video segments such as sponsored content.", compatiblePackages = [ CompatiblePackage( - "com.google.android.youtube", - [ + "com.google.android.youtube", [ "18.48.39", "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) ], dependencies = [ IntegrationsPatch::class, @@ -57,8 +60,8 @@ import com.android.tools.smali.dexlib2.iface.reference.StringReference // Used to prevent SponsorBlock from running on Shorts because SponsorBlock does not yet support Shorts. PlayerTypeHookPatch::class, PlayerControlsBytecodePatch::class, - SponsorBlockResourcePatch::class, - ], + SponsorBlockResourcePatch::class + ] ) @Suppress("unused") object SponsorBlockBytecodePatch : BytecodePatch( @@ -66,8 +69,8 @@ object SponsorBlockBytecodePatch : BytecodePatch( SeekbarFingerprint, AppendTimeFingerprint, LayoutConstructorFingerprint, - AutoRepeatParentFingerprint, - ), + AutoRepeatParentFingerprint + ) ) { private const val INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/sponsorblock/SegmentPlaybackController;" @@ -80,9 +83,8 @@ object SponsorBlockBytecodePatch : BytecodePatch( override fun execute(context: BytecodeContext) { LayoutConstructorFingerprint.result?.let { - if (!ControlsOverlayFingerprint.resolve(context, it.classDef)) { + if (!ControlsOverlayFingerprint.resolve(context, it.classDef)) throw ControlsOverlayFingerprint.exception - } } ?: throw LayoutConstructorFingerprint.exception /* @@ -91,7 +93,7 @@ object SponsorBlockBytecodePatch : BytecodePatch( with(VideoInformationPatch) { videoTimeHook( INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR, - "setVideoTime", + "setVideoTime" ) } @@ -119,7 +121,7 @@ object SponsorBlockBytecodePatch : BytecodePatch( seekbarMethod.addInstruction( moveRectangleToRegisterIndex + 1, "invoke-static/range {p0 .. p0}, " + - "$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;)V", + "$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;)V" ) for ((index, instruction) in seekbarMethodInstructions.withIndex()) { @@ -134,7 +136,7 @@ object SponsorBlockBytecodePatch : BytecodePatch( seekbarMethod.addInstruction( insertIndex, "invoke-static {v${invokeInstruction.registerC}}, " + - "$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarThickness(I)V", + "$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarThickness(I)V" ) break } @@ -152,7 +154,7 @@ object SponsorBlockBytecodePatch : BytecodePatch( } seekbarMethod.addInstruction( i, - "invoke-static {v$canvasInstance, v$centerY}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->drawSponsorTimeBars(Landroid/graphics/Canvas;F)V", + "invoke-static {v$canvasInstance, v$centerY}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->drawSponsorTimeBars(Landroid/graphics/Canvas;F)V" ) break @@ -186,7 +188,7 @@ object SponsorBlockBytecodePatch : BytecodePatch( """ 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 - """, + """ ) } @@ -199,7 +201,7 @@ object SponsorBlockBytecodePatch : BytecodePatch( """ invoke-static {p1}, $INTEGRATIONS_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->changeVisibilityNegatedImmediate(Z)V invoke-static {p1}, $INTEGRATIONS_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->changeVisibilityNegatedImmediate(Z)V - """.trimIndent(), + """.trimIndent() ) } } @@ -221,7 +223,7 @@ object SponsorBlockBytecodePatch : BytecodePatch( """ invoke-static {v$targetRegister}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->appendTimeWithoutSegments(Ljava/lang/String;)Ljava/lang/String; move-result-object v$targetRegister - """, + """ ) // initialize the player controller @@ -234,10 +236,10 @@ object SponsorBlockBytecodePatch : BytecodePatch( val frameLayoutRegister = (getInstruction(startIndex + 2) as OneRegisterInstruction).registerA addInstruction( startIndex + 3, - "invoke-static {v$frameLayoutRegister}, $INTEGRATIONS_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR->initialize(Landroid/view/ViewGroup;)V", + "invoke-static {v$frameLayoutRegister}, $INTEGRATIONS_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR->initialize(Landroid/view/ViewGroup;)V" ) } - } ?: throw ControlsOverlayFingerprint.exception + } ?: throw ControlsOverlayFingerprint.exception // get rectangle field name RectangleFieldInvalidatorFingerprint.resolve(context, seekbarSignatureResult.classDef) @@ -256,8 +258,7 @@ object SponsorBlockBytecodePatch : BytecodePatch( fun MutableMethod.replaceStringInstruction(index: Int, instruction: Instruction, with: String) { val register = (instruction as OneRegisterInstruction).registerA this.replaceInstruction( - index, - "const-string v$register, \"$with\"", + index, "const-string v$register, \"$with\"" ) } for ((index, it) in method.implementation!!.instructions.withIndex()) { @@ -267,12 +268,13 @@ object SponsorBlockBytecodePatch : BytecodePatch( "replaceMeWithsetSponsorBarRect" -> method.replaceStringInstruction( index, it, - rectangleFieldName, + rectangleFieldName ) } } } ?: throw PatchException("Could not find the method which contains the replaceMeWith* strings") + // The vote and create segment buttons automatically change their visibility when appropriate, // but if buttons are showing when the end of the video is reached then they will not automatically hide. // Add a hook to forcefully hide when the end of the video is reached. @@ -281,7 +283,7 @@ object SponsorBlockBytecodePatch : BytecodePatch( it.resolve(context, AutoRepeatParentFingerprint.result!!.classDef) }.result?.mutableMethod?.addInstruction( 0, - "invoke-static {}, $INTEGRATIONS_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR->endOfVideoReached()V", + "invoke-static {}, $INTEGRATIONS_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR->endOfVideoReached()V" ) ?: throw AutoRepeatFingerprint.exception // TODO: isSBChannelWhitelisting implementation diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/SpoofAppVersionPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/SpoofAppVersionPatch.kt index 3c092c4c6..b4a64d790 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/SpoofAppVersionPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/SpoofAppVersionPatch.kt @@ -17,12 +17,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @Patch( name = "Spoof app version", description = "Adds an option to trick YouTube into thinking you are running an older version of the app. " + - "This can be used to restore old UI elements and features.", + "This can be used to restore old UI elements and features.", dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class], compatiblePackages = [ CompatiblePackage( - "com.google.android.youtube", - [ + "com.google.android.youtube", [ "18.32.39", "18.37.36", "18.38.44", @@ -33,16 +32,20 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object SpoofAppVersionPatch : BytecodePatch( - setOf(SpoofAppVersionFingerprint), + setOf(SpoofAppVersionFingerprint) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/spoof/SpoofAppVersionPatch;" @@ -55,7 +58,7 @@ object SpoofAppVersionPatch : BytecodePatch( ListPreference( key = "revanced_spoof_app_version_target", summaryKey = null, - ), + ) ) SpoofAppVersionFingerprint.result?.apply { @@ -68,7 +71,7 @@ object SpoofAppVersionPatch : BytecodePatch( """ invoke-static {v$buildOverrideNameRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->getYouTubeVersionOverride(Ljava/lang/String;)Ljava/lang/String; move-result-object v$buildOverrideNameRegister - """, + """ ) } ?: throw SpoofAppVersionFingerprint.exception } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt index 637297905..7ed287816 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt @@ -27,8 +27,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class], compatiblePackages = [ CompatiblePackage( - "com.google.android.youtube", - [ + "com.google.android.youtube", [ "18.32.39", "18.37.36", "18.38.44", @@ -39,16 +38,20 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object DisableResumingShortsOnStartupPatch : BytecodePatch( - setOf(UserWasInShortsFingerprint), + setOf(UserWasInShortsFingerprint) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = @@ -58,14 +61,14 @@ object DisableResumingShortsOnStartupPatch : BytecodePatch( AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.SHORTS.addPreferences( - SwitchPreference("revanced_disable_resuming_shorts_player"), + SwitchPreference("revanced_disable_resuming_shorts_player") ) UserWasInShortsFingerprint.result?.mutableMethod?.apply { val listenableInstructionIndex = indexOfFirstInstruction { opcode == Opcode.INVOKE_INTERFACE && - getReference()?.definingClass == "Lcom/google/common/util/concurrent/ListenableFuture;" && - getReference()?.name == "isDone" + getReference()?.definingClass == "Lcom/google/common/util/concurrent/ListenableFuture;" && + getReference()?.name == "isDone" } if (listenableInstructionIndex < 0) throw PatchException("Could not find instruction index") val originalInstructionRegister = getInstruction(listenableInstructionIndex).registerC @@ -74,7 +77,7 @@ object DisableResumingShortsOnStartupPatch : BytecodePatch( // Replace original instruction to preserve control flow label. replaceInstruction( listenableInstructionIndex, - "invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z", + "invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z" ) addInstructionsWithLabels( listenableInstructionIndex + 1, @@ -84,7 +87,7 @@ object DisableResumingShortsOnStartupPatch : BytecodePatch( return-void :show_startup_shorts_player invoke-interface {v$originalInstructionRegister}, Lcom/google/common/util/concurrent/ListenableFuture;->isDone()Z - """, + """ ) } ?: throw UserWasInShortsFingerprint.exception } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/TabletMiniPlayerPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/TabletMiniPlayerPatch.kt index fbcdb512a..b770c7743 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/TabletMiniPlayerPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/TabletMiniPlayerPatch.kt @@ -26,8 +26,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class], compatiblePackages = [ CompatiblePackage( - "com.google.android.youtube", - arrayOf( + "com.google.android.youtube", arrayOf( "18.32.39", "18.37.36", "18.38.44", @@ -38,26 +37,30 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ), - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ) + ) + ] ) @Suppress("unused") object TabletMiniPlayerPatch : BytecodePatch( setOf( MiniPlayerDimensionsCalculatorParentFingerprint, MiniPlayerResponseModelSizeCheckFingerprint, - MiniPlayerOverrideFingerprint, - ), + MiniPlayerOverrideFingerprint + ) ) { override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences( - SwitchPreference("revanced_tablet_miniplayer"), + SwitchPreference("revanced_tablet_miniplayer") ) // First resolve the fingerprints via the parent fingerprint. @@ -74,8 +77,7 @@ object TabletMiniPlayerPatch : BytecodePatch( // Insert right before the return instruction. val secondInsertIndex = method.implementation!!.instructions.size - 1 method.insertOverride( - secondInsertIndex, - parameterRegister, + secondInsertIndex, parameterRegister /** same register used to return **/ ) @@ -127,7 +129,7 @@ object TabletMiniPlayerPatch : BytecodePatch( """ invoke-static {v$overrideRegister}, Lapp/revanced/integrations/youtube/patches/TabletMiniPlayerOverridePatch;->getTabletMiniPlayerOverride(Z)Z move-result v$overrideRegister - """, + """ ) } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemeBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemeBytecodePatch.kt index de120be0e..ac69564d2 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemeBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemeBytecodePatch.kt @@ -26,7 +26,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction ThemeResourcePatch::class, IntegrationsPatch::class, SettingsPatch::class, - AddResourcesPatch::class, + AddResourcesPatch::class ], compatiblePackages = [ CompatiblePackage( @@ -41,16 +41,20 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object ThemeBytecodePatch : BytecodePatch( - setOf(UseGradientLoadingScreenFingerprint), + setOf(UseGradientLoadingScreenFingerprint) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/theme/ThemePatch;" @@ -73,7 +77,7 @@ object ThemeBytecodePatch : BytecodePatch( "Dark green" to "#FF002905", "Dark yellow" to "#FF282900", "Dark orange" to "#FF291800", - "Dark red" to "#FF290000", + "Dark red" to "#FF290000" ), title = "Dark theme background color", description = "Can be a hex color (#AARRGGBB) or a color resource reference.", @@ -91,7 +95,7 @@ object ThemeBytecodePatch : BytecodePatch( "Light green" to "#FFCCFFCC", "Light yellow" to "#FFFDFFCC", "Light orange" to "#FFFFE6CC", - "Light red" to "#FFFFD6D6", + "Light red" to "#FFFFD6D6" ), title = "Light theme background color", description = "Can be a hex color (#AARRGGBB) or a color resource reference.", @@ -101,7 +105,7 @@ object ThemeBytecodePatch : BytecodePatch( AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences( - SwitchPreference("revanced_gradient_loading_screen"), + SwitchPreference("revanced_gradient_loading_screen") ) UseGradientLoadingScreenFingerprint.result?.mutableMethod?.apply { @@ -113,7 +117,7 @@ object ThemeBytecodePatch : BytecodePatch( """ invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->gradientLoadingScreenEnabled()Z move-result v$isEnabledRegister - """, + """ ) } ?: throw UseGradientLoadingScreenFingerprint.exception diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/thumbnails/AlternativeThumbnailsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/thumbnails/AlternativeThumbnailsPatch.kt index 4c642c7ba..2f624435b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/thumbnails/AlternativeThumbnailsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/thumbnails/AlternativeThumbnailsPatch.kt @@ -22,8 +22,10 @@ import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.reques import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnResponseStartedFingerprint import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnSucceededFingerprint import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch +import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch +import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch import app.revanced.patches.youtube.misc.settings.SettingsPatch -import app.revanced.util.exception +import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation @@ -38,6 +40,8 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class, + NavigationBarHookPatch::class, + PlayerTypeHookPatch::class ], compatiblePackages = [ CompatiblePackage( @@ -53,9 +57,13 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" ], ), ], @@ -123,32 +131,49 @@ object AlternativeThumbnailsPatch : BytecodePatch( override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) + val entries = "revanced_alt_thumbnail_options_entries" + val values = "revanced_alt_thumbnail_options_entry_values" SettingsPatch.PreferenceScreen.ALTERNATIVE_THUMBNAILS.addPreferences( - NonInteractivePreference( - "revanced_alt_thumbnail_about", - null, // Summary is dynamically updated based on the current settings. - tag = "app.revanced.integrations.youtube.settings.preference.AlternativeThumbnailsStatusPreference", + ListPreference("revanced_alt_thumbnail_home", + summaryKey = null, + entriesKey = entries, + entryValuesKey = values + ), + ListPreference("revanced_alt_thumbnail_subscription", + summaryKey = null, + entriesKey = entries, + entryValuesKey = values + ), + ListPreference("revanced_alt_thumbnail_library", + summaryKey = null, + entriesKey = entries, + entryValuesKey = values + ), + ListPreference("revanced_alt_thumbnail_player", + summaryKey = null, + entriesKey = entries, + entryValuesKey = values + ), + ListPreference("revanced_alt_thumbnail_search", + summaryKey = null, + entriesKey = entries, + entryValuesKey = values ), - SwitchPreference("revanced_alt_thumbnail_dearrow"), - SwitchPreference("revanced_alt_thumbnail_dearrow_connection_toast"), - TextPreference("revanced_alt_thumbnail_dearrow_api_url"), NonInteractivePreference( "revanced_alt_thumbnail_dearrow_about", // Custom about preference with link to the DeArrow website. tag = "app.revanced.integrations.youtube.settings.preference.AlternativeThumbnailsAboutDeArrowPreference", selectable = true, ), - SwitchPreference("revanced_alt_thumbnail_stills"), - ListPreference("revanced_alt_thumbnail_stills_time", summaryKey = null), - SwitchPreference("revanced_alt_thumbnail_stills_fast"), + SwitchPreference("revanced_alt_thumbnail_dearrow_connection_toast"), + TextPreference("revanced_alt_thumbnail_dearrow_api_url"), NonInteractivePreference("revanced_alt_thumbnail_stills_about"), + SwitchPreference("revanced_alt_thumbnail_stills_fast"), + ListPreference("revanced_alt_thumbnail_stills_time", summaryKey = null) ) - fun MethodFingerprint.getResultOrThrow() = - result ?: throw exception - fun MethodFingerprint.alsoResolve(fingerprint: MethodFingerprint) = - also { resolve(context, fingerprint.getResultOrThrow().classDef) }.getResultOrThrow() + also { resolve(context, fingerprint.resultOrThrow().classDef) }.resultOrThrow() fun MethodFingerprint.resolveAndLetMutableMethod( fingerprint: MethodFingerprint, @@ -172,7 +197,7 @@ object AlternativeThumbnailsPatch : BytecodePatch( // The URL is required for the failure callback hook, but the URL field is obfuscated. // Add a helper get method that returns the URL field. - RequestFingerprint.getResultOrThrow().apply { + RequestFingerprint.resultOrThrow().apply { // The url is the only string field that is set inside the constructor. val urlFieldInstruction = mutableMethod.getInstructions().first { if (it.opcode != Opcode.IPUT_OBJECT) return@first false diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/AutoRepeatPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/AutoRepeatPatch.kt index 144a27ac7..55c110966 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/AutoRepeatPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/AutoRepeatPatch.kt @@ -14,10 +14,11 @@ import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatParen import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.settings.SettingsPatch + @Patch( name = "Always repeat", description = "Adds an option to always repeat videos when they end.", - dependencies = [IntegrationsPatch::class, AddResourcesPatch::class], + dependencies = [IntegrationsPatch::class,AddResourcesPatch::class], compatiblePackages = [ CompatiblePackage( "com.google.android.youtube", @@ -32,40 +33,44 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object AutoRepeatPatch : BytecodePatch( - setOf(AutoRepeatParentFingerprint), + setOf(AutoRepeatParentFingerprint) ) { override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.MISC.addPreferences( - SwitchPreference("revanced_auto_repeat"), + SwitchPreference("revanced_auto_repeat") ) - // Get Result from the ParentFingerprint which is the playMethod we need to get. + //Get Result from the ParentFingerprint which is the playMethod we need to get. val parentResult = AutoRepeatParentFingerprint.result ?: throw PatchException("ParentFingerprint did not resolve.") - // this one needs to be called when app/revanced/integrations/youtube/patches/AutoRepeatPatch;->shouldAutoRepeat() returns true + //this one needs to be called when app/revanced/integrations/youtube/patches/AutoRepeatPatch;->shouldAutoRepeat() returns true val playMethod = parentResult.mutableMethod AutoRepeatFingerprint.resolve(context, parentResult.classDef) - // String is: Laamp;->E()V + //String is: Laamp;->E()V val methodToCall = playMethod.definingClass + "->" + playMethod.name + "()V" - // This is the method we search for + //This is the method we search for val result = AutoRepeatFingerprint.result ?: throw PatchException("FingerPrint did not resolve.") val method = result.mutableMethod - // Instructions to add to the smali code + //Instructions to add to the smali code val instructions = """ invoke-static {}, Lapp/revanced/integrations/youtube/patches/AutoRepeatPatch;->shouldAutoRepeat()Z move-result v0 @@ -75,19 +80,20 @@ object AutoRepeatPatch : BytecodePatch( return-void """ - // Get the implementation so we can do a check for null and get instructions size. + //Get the implementation so we can do a check for null and get instructions size. val implementation = method.implementation ?: throw PatchException("No Method Implementation found!") - // Since addInstructions needs an index which starts counting at 0 and size starts counting at 1, - // we have to remove 1 to get the latest instruction + //Since addInstructions needs an index which starts counting at 0 and size starts counting at 1, + //we have to remove 1 to get the latest instruction val index = implementation.instructions.size - 1 - // remove last instruction which is return-void + + //remove last instruction which is return-void method.removeInstruction(index) // Add our own instructions there method.addInstructionsWithLabels(index, instructions) - // Everything worked as expected, return Success + //Everything worked as expected, return Success } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/dimensions/spoof/SpoofDeviceDimensionsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/dimensions/spoof/SpoofDeviceDimensionsPatch.kt index c2c381d15..123bbd356 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/dimensions/spoof/SpoofDeviceDimensionsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/dimensions/spoof/SpoofDeviceDimensionsPatch.kt @@ -28,16 +28,20 @@ import app.revanced.util.exception "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object SpoofDeviceDimensionsPatch : BytecodePatch( - setOf(DeviceDimensionsModelToStringFingerprint), + setOf(DeviceDimensionsModelToStringFingerprint) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/spoof/SpoofDeviceDimensionsPatch;" @@ -46,7 +50,7 @@ object SpoofDeviceDimensionsPatch : BytecodePatch( AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.MISC.addPreferences( - SwitchPreference("revanced_spoof_device_dimensions"), + SwitchPreference("revanced_spoof_device_dimensions") ) DeviceDimensionsModelToStringFingerprint.result @@ -58,13 +62,13 @@ object SpoofDeviceDimensionsPatch : BytecodePatch( 1 to "MinHeightOrWidth", // p1 = min height 2 to "MaxHeightOrWidth", // p2 = max height 3 to "MinHeightOrWidth", // p3 = min width - 4 to "MaxHeightOrWidth", // p4 = max width + 4 to "MaxHeightOrWidth" // p4 = max width ).map { (parameter, method) -> """ invoke-static { p$parameter }, $INTEGRATIONS_CLASS_DESCRIPTOR->get$method(I)I move-result p$parameter """ - }.joinToString("\n") { it }, + }.joinToString("\n") { it } ) ?: throw DeviceDimensionsModelToStringFingerprint.exception } -} +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/ClientSpoofPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/ClientSpoofPatch.kt index a34efc1c1..aeb1788d7 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/ClientSpoofPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/ClientSpoofPatch.kt @@ -1,47 +1,86 @@ package app.revanced.patches.youtube.misc.fix.playback -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.youtube.misc.fix.playback.fingerprints.UserAgentHeaderBuilderFingerprint -import app.revanced.util.exception -import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod +import app.revanced.patches.all.misc.transformation.BaseTransformInstructionsPatch +import app.revanced.patches.all.misc.transformation.IMethodCall +import app.revanced.patches.all.misc.transformation.Instruction35cInfo +import app.revanced.patches.all.misc.transformation.filterMapInstruction35c +import app.revanced.util.getReference +import com.android.tools.smali.dexlib2.iface.ClassDef +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.instruction.Instruction +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Patch( name = "Client spoof", - description = "Adds options to spoof the client to allow video playback.", - dependencies = [SpoofSignaturePatch::class], + description = "Spoofs the client to allow video playback.", compatiblePackages = [ - CompatiblePackage( - "com.google.android.youtube", - [ - "18.48.39", - "18.49.37", - "19.01.34", - "19.02.39", - "19.03.35", - "19.03.36", - "19.04.37", - ], - ), + CompatiblePackage("com.google.android.youtube"), ], ) -object ClientSpoofPatch : BytecodePatch( - setOf(UserAgentHeaderBuilderFingerprint), -) { +object ClientSpoofPatch : BaseTransformInstructionsPatch() { private const val ORIGINAL_PACKAGE_NAME = "com.google.android.youtube" + private const val USER_AGENT_STRING_BUILDER_APPEND_METHOD_REFERENCE = + "Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;" - override fun execute(context: BytecodeContext) { - UserAgentHeaderBuilderFingerprint.result?.let { result -> - val insertIndex = result.scanResult.patternScanResult!!.endIndex - result.mutableMethod.apply { - val packageNameRegister = getInstruction(insertIndex).registerD + override fun filterMap( + classDef: ClassDef, + method: Method, + instruction: Instruction, + instructionIndex: Int, + ) = filterMapInstruction35c( + "Lapp/revanced/integrations", + classDef, + instruction, + instructionIndex, + ) - addInstruction(insertIndex, "const-string v$packageNameRegister, \"$ORIGINAL_PACKAGE_NAME\"") + override fun transform(mutableMethod: MutableMethod, entry: Instruction35cInfo) { + val (_, _, instructionIndex) = entry + + // Replace the result of context.getPackageName(), if it is used in a user agent string. + mutableMethod.apply { + // After context.getPackageName() the result is moved to a register. + val targetRegister = ( + getInstruction(instructionIndex + 1) + as? OneRegisterInstruction ?: return + ).registerA + + // IndexOutOfBoundsException is not possible here, + // but no such occurrences are present in the app. + val referee = getInstruction(instructionIndex + 2).getReference()?.toString() + + // This can technically also match non-user agent string builder append methods, + // but no such occurrences are present in the app. + if (referee != USER_AGENT_STRING_BUILDER_APPEND_METHOD_REFERENCE) { + return } - } ?: throw UserAgentHeaderBuilderFingerprint.exception + + // Overwrite the result of context.getPackageName() with the original package name. + replaceInstruction( + instructionIndex + 1, + "const-string v$targetRegister, \"${ORIGINAL_PACKAGE_NAME}\"", + ) + } + } + + @Suppress("unused") + private enum class MethodCall( + override val definedClassName: String, + override val methodName: String, + override val methodParams: Array, + override val returnType: String, + ) : IMethodCall { + GetPackageName( + "Landroid/content/Context;", + "getPackageName", + emptyArray(), + "Ljava/lang/String;", + ), } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt index 5a00c7918..4e9a7833c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofSignaturePatch.kt @@ -13,21 +13,11 @@ import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.misc.fix.playback.fingerprints.* -import app.revanced.patches.youtube.misc.fix.playback.fingerprints.ParamsMapPutFingerprint -import app.revanced.patches.youtube.misc.fix.playback.fingerprints.PlayerResponseModelImplGeneralFingerprint -import app.revanced.patches.youtube.misc.fix.playback.fingerprints.PlayerResponseModelImplLiveStreamFingerprint -import app.revanced.patches.youtube.misc.fix.playback.fingerprints.PlayerResponseModelImplRecommendedLevelFingerprint -import app.revanced.patches.youtube.misc.fix.playback.fingerprints.ScrubbedPreviewLayoutFingerprint -import app.revanced.patches.youtube.misc.fix.playback.fingerprints.StoryboardRendererDecoderRecommendedLevelFingerprint -import app.revanced.patches.youtube.misc.fix.playback.fingerprints.StoryboardRendererDecoderSpecFingerprint -import app.revanced.patches.youtube.misc.fix.playback.fingerprints.StoryboardRendererSpecFingerprint -import app.revanced.patches.youtube.misc.fix.playback.fingerprints.StoryboardThumbnailFingerprint -import app.revanced.patches.youtube.misc.fix.playback.fingerprints.StoryboardThumbnailParentFingerprint import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch import app.revanced.patches.youtube.misc.settings.SettingsPatch import app.revanced.patches.youtube.video.information.VideoInformationPatch import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch -import app.revanced.util.* +import app.revanced.util.exception import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction @@ -43,6 +33,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction AddResourcesPatch::class, ], ) +@Deprecated("This patch will be removed in the future.") object SpoofSignaturePatch : BytecodePatch( setOf( PlayerResponseModelImplGeneralFingerprint, diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/UserAgentHeaderBuilderFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/UserAgentHeaderBuilderFingerprint.kt deleted file mode 100644 index 209b0b165..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/UserAgentHeaderBuilderFingerprint.kt +++ /dev/null @@ -1,10 +0,0 @@ -package app.revanced.patches.youtube.misc.fix.playback.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.Opcode - -internal object UserAgentHeaderBuilderFingerprint : MethodFingerprint( - parameters = listOf("L", "L", "L"), - opcodes = listOf(Opcode.MOVE_RESULT_OBJECT, Opcode.INVOKE_VIRTUAL), - strings = listOf("(Linux; U; Android "), -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt index e8be6f56b..ff2902351 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt @@ -6,7 +6,7 @@ import app.revanced.patches.youtube.layout.buttons.cast.HideCastButtonPatch import app.revanced.patches.youtube.misc.fix.playback.ClientSpoofPatch import app.revanced.patches.youtube.misc.gms.Constants.REVANCED_YOUTUBE_PACKAGE_NAME import app.revanced.patches.youtube.misc.gms.Constants.YOUTUBE_PACKAGE_NAME -import app.revanced.patches.youtube.misc.gms.GmsCoreSupportResourcePatch.gmsCoreVendorOption +import app.revanced.patches.youtube.misc.gms.GmsCoreSupportResourcePatch.gmsCoreVendorGroupIdOption import app.revanced.patches.youtube.misc.gms.fingerprints.* import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.shared.fingerprints.HomeActivityFingerprint @@ -38,9 +38,13 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch( "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37", ), ), ), @@ -53,5 +57,5 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch( PrimeMethodFingerprint, ), ) { - override val gmsCoreVendor by gmsCoreVendorOption + override val gmsCoreVendor by gmsCoreVendorGroupIdOption } diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportResourcePatch.kt index f4803ae29..730d921a4 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportResourcePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportResourcePatch.kt @@ -21,7 +21,7 @@ object GmsCoreSupportResourcePatch : BaseGmsCoreSupportResourcePatch( IntentPreference( "microg_settings", intent = IntentPreference.Intent("", "org.microg.gms.ui.SettingsActivity") { - "$gmsCoreVendor.android.gms" + "$gmsCoreVendorGroupId.android.gms" }, ), ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/links/BypassURLRedirectsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/links/BypassURLRedirectsPatch.kt index ab37e0e23..3228a7c68 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/links/BypassURLRedirectsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/links/BypassURLRedirectsPatch.kt @@ -30,27 +30,31 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object BypassURLRedirectsPatch : BytecodePatch( - setOf(ABUriParserFingerprint, HTTPUriParserFingerprint), + setOf(ABUriParserFingerprint, HTTPUriParserFingerprint) ) { override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.MISC.addPreferences( - SwitchPreference("revanced_bypass_url_redirects"), + SwitchPreference("revanced_bypass_url_redirects") ) mapOf( ABUriParserFingerprint to 7, // Offset to Uri.parse. - HTTPUriParserFingerprint to 0, // Offset to Uri.parse. + HTTPUriParserFingerprint to 0 // Offset to Uri.parse. ).map { (fingerprint, offset) -> (fingerprint.result ?: throw fingerprint.exception) to offset }.forEach { (result, offset) -> @@ -61,11 +65,11 @@ object BypassURLRedirectsPatch : BytecodePatch( replaceInstruction( insertIndex, "invoke-static {v$uriStringRegister}," + - "Lapp/revanced/integrations/youtube/patches/BypassURLRedirectsPatch;" + - "->" + - "parseRedirectUri(Ljava/lang/String;)Landroid/net/Uri;", + "Lapp/revanced/integrations/youtube/patches/BypassURLRedirectsPatch;" + + "->" + + "parseRedirectUri(Ljava/lang/String;)Landroid/net/Uri;" ) } } } -} +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/links/OpenLinksExternallyPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/links/OpenLinksExternallyPatch.kt index 05c21e58d..682868644 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/links/OpenLinksExternallyPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/links/OpenLinksExternallyPatch.kt @@ -34,20 +34,22 @@ import com.android.tools.smali.dexlib2.iface.reference.StringReference "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") -object OpenLinksExternallyPatch : BaseTransformInstructionsPatch>() { +object OpenLinksExternallyPatch : BaseTransformInstructionsPatch>( +) { override fun filterMap( - classDef: ClassDef, - method: Method, - instruction: Instruction, - instructionIndex: Int, + classDef: ClassDef, method: Method, instruction: Instruction, instructionIndex: Int ): Pair? { if (instruction !is ReferenceInstruction) return null val reference = instruction.reference as? StringReference ?: return null @@ -66,7 +68,7 @@ object OpenLinksExternallyPatch : BaseTransformInstructionsPatch> """ invoke-static {v$register}, Lapp/revanced/integrations/youtube/patches/OpenLinksExternallyPatch;->getIntent(Ljava/lang/String;)Ljava/lang/String; move-result-object v$register - """, + """ ) } @@ -74,9 +76,9 @@ object OpenLinksExternallyPatch : BaseTransformInstructionsPatch> AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.MISC.addPreferences( - SwitchPreference("revanced_external_browser"), + SwitchPreference("revanced_external_browser") ) super.execute(context) } -} +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt index a9877a491..37fa28b95 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt @@ -1,5 +1,6 @@ package app.revanced.patches.youtube.misc.litho.filter +import app.revanced.util.exception import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstructions @@ -9,27 +10,30 @@ import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.litho.filter.fingerprints.* -import app.revanced.util.exception +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction +import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.Instruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.TypeReference import java.io.Closeable @Patch( description = "Hooks the method which parses the bytes into a ComponentContext to filter components.", - dependencies = [IntegrationsPatch::class], + dependencies = [IntegrationsPatch::class] ) @Suppress("unused") -object LithoFilterPatch : - BytecodePatch( - setOf(ComponentContextParserFingerprint, LithoFilterFingerprint, ProtobufBufferReferenceFingerprint), - ), - Closeable { +object LithoFilterPatch : BytecodePatch( + setOf(ComponentContextParserFingerprint, LithoFilterFingerprint, ProtobufBufferReferenceFingerprint) +), Closeable { private val MethodFingerprint.patternScanResult get() = result!!.scanResult.patternScanResult!! @@ -82,7 +86,7 @@ object LithoFilterPatch : ComponentContextParserFingerprint.result?.also { arrayOf( EmptyComponentBuilderFingerprint, - ReadComponentIdentifierFingerprint, + ReadComponentIdentifierFingerprint ).forEach { fingerprint -> if (fingerprint.resolve(context, it.mutableMethod, it.mutableClass)) return@forEach throw fingerprint.exception @@ -92,10 +96,8 @@ object LithoFilterPatch : // region Pass the buffer into Integrations. ProtobufBufferReferenceFingerprint.result - ?.mutableMethod?.addInstruction( - 0, - " invoke-static { p2 }, $INTEGRATIONS_CLASS_DESCRIPTOR->setProtoBuffer(Ljava/nio/ByteBuffer;)V", - ) + ?.mutableMethod?.addInstruction(0, + " invoke-static { p2 }, $INTEGRATIONS_CLASS_DESCRIPTOR->setProtoBuffer(Ljava/nio/ByteBuffer;)V") ?: throw ProtobufBufferReferenceFingerprint.exception // endregion @@ -106,7 +108,11 @@ object LithoFilterPatch : val emptyComponentFieldIndex = builderMethodIndex + 2 bytesToComponentContextMethod.mutableMethod.apply { - val insertHookIndex = bytesToComponentContextMethod.scanResult.patternScanResult!!.endIndex + 1 + val insertHookIndex = indexOfFirstInstruction { + opcode == Opcode.IPUT_OBJECT && + getReference()?.type == "Ljava/lang/StringBuilder;" + } + 1 + if (insertHookIndex <= 0) throw PatchException("Could not find insert index") // region Get free registers that this patch uses. // Registers are overwritten right after they are used in this patch, therefore free to clobber. @@ -156,7 +162,7 @@ object LithoFilterPatch : return-object v$free2 """, // Used to jump over the instruction which block the component from being created. - ExternalLabel("unfiltered", getInstruction(insertHookIndex)), + ExternalLabel("unfiltered", getInstruction(insertHookIndex)) ) // endregion } @@ -175,7 +181,7 @@ object LithoFilterPatch : invoke-direct {v1}, $classDescriptor->()V const/16 v2, ${filterCount++} aput-object v1, v0, v2 - """, + """ ) } } ?: throw LithoFilterFingerprint.exception diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ComponentContextParserFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ComponentContextParserFingerprint.kt index 9c8a506b8..419e0f91c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ComponentContextParserFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ComponentContextParserFingerprint.kt @@ -1,13 +1,7 @@ package app.revanced.patches.youtube.misc.litho.filter.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.Opcode internal object ComponentContextParserFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.INVOKE_VIRTUAL, - Opcode.IPUT_OBJECT, - ), - strings = listOf("Component was not found %s because it was removed due to duplicate converter bindings."), -) + strings = listOf("Component was not found %s because it was removed due to duplicate converter bindings.") +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/MinimizedPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/MinimizedPlaybackPatch.kt index ea8082701..4374262a3 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/MinimizedPlaybackPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/MinimizedPlaybackPatch.kt @@ -29,7 +29,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference PlayerTypeHookPatch::class, VideoInformationPatch::class, SettingsPatch::class, - AddResourcesPatch::class, + AddResourcesPatch::class ], compatiblePackages = [ CompatiblePackage( @@ -39,20 +39,24 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object MinimizedPlaybackPatch : BytecodePatch( setOf( MinimizedPlaybackManagerFingerprint, MinimizedPlaybackSettingsParentFingerprint, - KidsMinimizedPlaybackPolicyControllerFingerprint, - ), + KidsMinimizedPlaybackPolicyControllerFingerprint + ) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/MinimizedPlaybackPatch;" @@ -61,7 +65,7 @@ object MinimizedPlaybackPatch : BytecodePatch( AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.MISC.addPreferences( - NonInteractivePreference("revanced_minimized_playback"), + NonInteractivePreference("revanced_minimized_playback") ) MinimizedPlaybackManagerFingerprint.result?.apply { @@ -71,7 +75,7 @@ object MinimizedPlaybackPatch : BytecodePatch( invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->playbackIsNotShort()Z move-result v0 return v0 - """, + """ ) } ?: throw MinimizedPlaybackManagerFingerprint.exception @@ -79,7 +83,7 @@ object MinimizedPlaybackPatch : BytecodePatch( MinimizedPlaybackSettingsParentFingerprint.result ?: throw MinimizedPlaybackSettingsParentFingerprint.exception MinimizedPlaybackSettingsFingerprint.resolve( context, - MinimizedPlaybackSettingsParentFingerprint.result!!.classDef, + MinimizedPlaybackSettingsParentFingerprint.result!!.classDef ) MinimizedPlaybackSettingsFingerprint.result?.apply { val booleanCalls = method.implementation!!.instructions.withIndex() @@ -95,7 +99,7 @@ object MinimizedPlaybackPatch : BytecodePatch( invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->overrideMinimizedPlaybackAvailable()Z move-result v0 return v0 - """, + """ ) } ?: throw MinimizedPlaybackSettingsFingerprint.exception @@ -104,7 +108,7 @@ object MinimizedPlaybackPatch : BytecodePatch( KidsMinimizedPlaybackPolicyControllerFingerprint.result?.apply { mutableMethod.addInstruction( 0, - "return-void", + "return-void" ) } ?: throw KidsMinimizedPlaybackPolicyControllerFingerprint.exception } diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt new file mode 100644 index 000000000..5b19cdc0a --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt @@ -0,0 +1,130 @@ +package app.revanced.patches.youtube.misc.navigation + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.extensions.InstructionExtensions.getInstructions +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.PatchException +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod +import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch +import app.revanced.patches.youtube.misc.navigation.fingerprints.* +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction +import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.instruction.Instruction +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference +import com.android.tools.smali.dexlib2.util.MethodUtil + +@Patch( + description = "Hooks the active navigation or search bar.", + dependencies = [ + IntegrationsPatch::class, + NavigationBarHookResourcePatch::class, + ], +) +@Suppress("unused") +object NavigationBarHookPatch : BytecodePatch( + setOf( + PivotBarConstructorFingerprint, + NavigationEnumFingerprint, + PivotBarButtonsCreateDrawableViewFingerprint, + PivotBarButtonsCreateResourceViewFingerprint, + NavigationBarHookCallbackFingerprint, + ActionBarSearchResultsFingerprint, + ), +) { + internal const val INTEGRATIONS_CLASS_DESCRIPTOR = + "Lapp/revanced/integrations/youtube/shared/NavigationBar;" + + internal const val INTEGRATIONS_NAVIGATION_BUTTON_DESCRIPTOR = + "Lapp/revanced/integrations/youtube/shared/NavigationBar\$NavigationButton;" + + override fun execute(context: BytecodeContext) { + fun MutableMethod.addHook(hook: Hook, insertPredicate: Instruction.() -> Boolean) { + val filtered = getInstructions().filter(insertPredicate) + if (filtered.isEmpty()) throw PatchException("Could not find insert indexes") + filtered.forEach { + val insertIndex = it.location.index + 2 + val register = getInstruction(insertIndex - 1).registerA + + addInstruction( + insertIndex, + "invoke-static { v$register }, " + + "$INTEGRATIONS_CLASS_DESCRIPTOR->${hook.methodName}(${hook.parameters})V", + ) + } + } + + InitializeButtonsFingerprint.apply { + resolve(context, PivotBarConstructorFingerprint.resultOrThrow().classDef) + }.resultOrThrow().mutableMethod.apply { + // Hook the current navigation bar enum value. Note, the 'You' tab does not have an enum value. + val navigationEnumClassName = NavigationEnumFingerprint.resultOrThrow().mutableClass.type + addHook(Hook.SET_LAST_APP_NAVIGATION_ENUM) { + opcode == Opcode.INVOKE_STATIC && + getReference()?.definingClass == navigationEnumClassName + } + + // Hook the creation of navigation tab views. + val drawableTabMethod = PivotBarButtonsCreateDrawableViewFingerprint.resultOrThrow().mutableMethod + addHook(Hook.NAVIGATION_TAB_LOADED) predicate@{ + MethodUtil.methodSignaturesMatch( + getReference() ?: return@predicate false, + drawableTabMethod, + ) + } + + val imageResourceTabMethod = PivotBarButtonsCreateResourceViewFingerprint.resultOrThrow().method + addHook(Hook.NAVIGATION_IMAGE_RESOURCE_TAB_LOADED) predicate@{ + MethodUtil.methodSignaturesMatch( + getReference() ?: return@predicate false, + imageResourceTabMethod, + ) + } + } + + // Hook the search bar. + + // Two different layouts are used at the hooked code. + // Insert before the first ViewGroup method call after inflating, + // so this works regardless which layout is used. + ActionBarSearchResultsFingerprint.resultOrThrow().mutableMethod.apply { + val instructionIndex = indexOfFirstInstruction { + opcode == Opcode.INVOKE_VIRTUAL && getReference()?.name == "setLayoutDirection" + } + + val viewRegister = getInstruction(instructionIndex).registerC + + addInstruction( + instructionIndex, + "invoke-static { v$viewRegister }, " + + "$INTEGRATIONS_CLASS_DESCRIPTOR->searchBarResultsViewLoaded(Landroid/view/View;)V", + ) + } + } + + val hookNavigationButtonCreated: (String) -> Unit by lazy { + val method = NavigationBarHookCallbackFingerprint.resultOrThrow().mutableMethod + + { integrationsClassDescriptor -> + method.addInstruction( + 0, + "invoke-static { p0, p1 }, " + + "$integrationsClassDescriptor->navigationTabCreated" + + "(${INTEGRATIONS_NAVIGATION_BUTTON_DESCRIPTOR}Landroid/view/View;)V", + ) + } + } + + private enum class Hook(val methodName: String, val parameters: String) { + SET_LAST_APP_NAVIGATION_ENUM("setLastAppNavigationEnum", "Ljava/lang/Enum;"), + NAVIGATION_TAB_LOADED("navigationTabLoaded", "Landroid/view/View;"), + NAVIGATION_IMAGE_RESOURCE_TAB_LOADED("navigationImageResourceTabLoaded", "Landroid/view/View;"), + SEARCH_BAR_RESULTS_VIEW_LOADED("searchBarResultsViewLoaded", "Landroid/view/View;"), + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookResourcePatch.kt new file mode 100644 index 000000000..3841f2bfa --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookResourcePatch.kt @@ -0,0 +1,24 @@ +package app.revanced.patches.youtube.misc.navigation + +import app.revanced.patcher.data.ResourceContext +import app.revanced.patcher.patch.ResourcePatch +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patches.shared.misc.mapping.ResourceMappingPatch + +@Patch( + dependencies = [ResourceMappingPatch::class] +) +internal object NavigationBarHookResourcePatch : ResourcePatch() { + internal var imageOnlyTabResourceId: Long = -1 + internal var actionBarSearchResultsViewMicId: Long = -1 + + override fun execute(context: ResourceContext) { + imageOnlyTabResourceId = ResourceMappingPatch.resourceMappings.first { + it.type == "layout" && it.name == "image_only_tab" + }.id + + actionBarSearchResultsViewMicId = ResourceMappingPatch.resourceMappings.first { + it.type == "layout" && it.name == "action_bar_search_results_view_mic" + }.id + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/ActionBarSearchResultsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/ActionBarSearchResultsFingerprint.kt new file mode 100644 index 000000000..2ba8106f9 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/ActionBarSearchResultsFingerprint.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.youtube.misc.navigation.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patches.youtube.misc.navigation.NavigationBarHookResourcePatch +import app.revanced.util.patch.LiteralValueFingerprint +import com.android.tools.smali.dexlib2.AccessFlags + +internal object ActionBarSearchResultsFingerprint : LiteralValueFingerprint( + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + returnType = "Landroid/view/View;", + parameters = listOf("Landroid/view/LayoutInflater;"), + literalSupplier = { NavigationBarHookResourcePatch.actionBarSearchResultsViewMicId } +) \ 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/misc/navigation/fingerprints/InitializeButtonsFingerprint.kt similarity index 51% rename from src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/InitializeButtonsFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/InitializeButtonsFingerprint.kt index a3d8ef690..f91d1b36f 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/InitializeButtonsFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/InitializeButtonsFingerprint.kt @@ -1,13 +1,16 @@ -package app.revanced.patches.youtube.layout.buttons.navigation.fingerprints +package app.revanced.patches.youtube.misc.navigation.fingerprints import app.revanced.patcher.extensions.or -import app.revanced.patches.youtube.layout.buttons.navigation.ResolvePivotBarFingerprintsPatch +import app.revanced.patches.youtube.misc.navigation.NavigationBarHookResourcePatch import app.revanced.util.patch.LiteralValueFingerprint import com.android.tools.smali.dexlib2.AccessFlags +/** + * Resolves to the class found in [PivotBarConstructorFingerprint]. + */ internal object InitializeButtonsFingerprint : LiteralValueFingerprint( accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, returnType = "V", parameters = listOf(), - literalSupplier = { ResolvePivotBarFingerprintsPatch.imageOnlyTabResourceId }, -) + literalSupplier = { NavigationBarHookResourcePatch.imageOnlyTabResourceId } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/NavigationBarHookCallbackFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/NavigationBarHookCallbackFingerprint.kt new file mode 100644 index 000000000..1d69dfe89 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/NavigationBarHookCallbackFingerprint.kt @@ -0,0 +1,21 @@ +package app.revanced.patches.youtube.misc.navigation.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.youtube.layout.buttons.navigation.NavigationButtonsPatch +import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch +import com.android.tools.smali.dexlib2.AccessFlags + +/** + * Integrations method, used for callback into to other patches. + * Specifically, [NavigationButtonsPatch]. + */ +internal object NavigationBarHookCallbackFingerprint : MethodFingerprint( + accessFlags = AccessFlags.PRIVATE or AccessFlags.STATIC, + returnType = "V", + parameters = listOf(NavigationBarHookPatch.INTEGRATIONS_NAVIGATION_BUTTON_DESCRIPTOR, "Landroid/view/View;"), + customFingerprint = { methodDef, _ -> + methodDef.name == "navigationTabCreatedCallback" && + methodDef.definingClass == NavigationBarHookPatch.INTEGRATIONS_CLASS_DESCRIPTOR + }, +) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/NavigationEnumFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/NavigationEnumFingerprint.kt new file mode 100644 index 000000000..c084cf5ec --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/NavigationEnumFingerprint.kt @@ -0,0 +1,21 @@ +package app.revanced.patches.youtube.misc.navigation.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags + +/** + * Resolves to the Enum class that looks up ordinal -> instance. + */ +internal object NavigationEnumFingerprint : MethodFingerprint( + accessFlags = AccessFlags.STATIC or AccessFlags.CONSTRUCTOR, + strings = listOf( + "PIVOT_HOME", + "TAB_SHORTS", + "CREATION_TAB_LARGE", + "PIVOT_SUBSCRIPTIONS", + "TAB_ACTIVITY", + "VIDEO_LIBRARY_WHITE", + "INCOGNITO_CIRCLE" + ) +) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarButtonsCreateDrawableViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarButtonsCreateDrawableViewFingerprint.kt new file mode 100644 index 000000000..0192f6e3d --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarButtonsCreateDrawableViewFingerprint.kt @@ -0,0 +1,17 @@ +package app.revanced.patches.youtube.misc.navigation.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags + +internal object PivotBarButtonsCreateDrawableViewFingerprint : MethodFingerprint( + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + // Method has different number of parameters in some app targets. + // Parameters are checked in custom fingerprint. + returnType = "Landroid/view/View;", + customFingerprint = { methodDef, classDef -> + classDef.type == "Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;" && + // Only one method has a Drawable parameter. + methodDef.parameterTypes.firstOrNull() == "Landroid/graphics/drawable/Drawable;" + } +) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarButtonsCreateResourceViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarButtonsCreateResourceViewFingerprint.kt new file mode 100644 index 000000000..cef0b517e --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarButtonsCreateResourceViewFingerprint.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.youtube.misc.navigation.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags + +internal object PivotBarButtonsCreateResourceViewFingerprint : MethodFingerprint( + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + parameters = listOf("L", "Z", "I", "L"), + returnType = "Landroid/view/View;", + customFingerprint = { _, classDef -> + classDef.type == "Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;" + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarConstructorFingerprint.kt similarity index 82% rename from src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarConstructorFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarConstructorFingerprint.kt index 1e9c38ee7..2361994a8 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarConstructorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarConstructorFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.youtube.layout.buttons.navigation.fingerprints +package app.revanced.patches.youtube.misc.navigation.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/PlayerOverlaysHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/PlayerOverlaysHookPatch.kt index f7f8a3b38..c94ac05d6 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/PlayerOverlaysHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/PlayerOverlaysHookPatch.kt @@ -3,33 +3,31 @@ package app.revanced.patches.youtube.misc.playeroverlay import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.playeroverlay.fingerprint.PlayerOverlaysOnFinishInflateFingerprint +import app.revanced.util.exception @Patch( - description = "Hook for adding custom overlays to the video player.", + description = "Hook for the video player overlay", dependencies = [IntegrationsPatch::class], - compatiblePackages = [ - CompatiblePackage( - "com.google.android.youtube", - [ - "18.32.39", - ], - ), - ], ) + +/** + * Edit: This patch is not in use and may not work. + */ @Suppress("unused") -object PlayerOverlaysHookPatch : BytecodePatch( // TODO: delete this unused outdated patch and its integration code. - setOf(PlayerOverlaysOnFinishInflateFingerprint), +object PlayerOverlaysHookPatch : BytecodePatch( + setOf(PlayerOverlaysOnFinishInflateFingerprint) ) { + private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/PlayerOverlaysHookPatch;" + override fun execute(context: BytecodeContext) { - // hook YouTubePlayerOverlaysLayout.onFinishInflate() - val method = PlayerOverlaysOnFinishInflateFingerprint.result!!.mutableMethod - method.addInstruction( - method.implementation!!.instructions.size - 2, - "invoke-static { p0 }, Lapp/revanced/integrations/youtube/patches/PlayerOverlaysHookPatch;->YouTubePlayerOverlaysLayout_onFinishInflateHook(Ljava/lang/Object;)V", - ) + PlayerOverlaysOnFinishInflateFingerprint.result?.mutableMethod?.apply { + addInstruction( + implementation!!.instructions.lastIndex, + "invoke-static { p0 }, $INTEGRATIONS_CLASS_DESCRIPTOR->playerOverlayInflated(Landroid/view/ViewGroup;)V" + ) + } ?: throw PlayerOverlaysOnFinishInflateFingerprint.exception } -} +} \ No newline at end of file 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 f66bf208c..11658c958 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 @@ -1,9 +1,14 @@ package app.revanced.patches.youtube.misc.playeroverlay.fingerprint +import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags internal object PlayerOverlaysOnFinishInflateFingerprint : MethodFingerprint( + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + returnType = "V", customFingerprint = { methodDef, _ -> - methodDef.definingClass.endsWith("YouTubePlayerOverlaysLayout;") && methodDef.name == "onFinishInflate" + methodDef.definingClass.endsWith("/YouTubePlayerOverlaysLayout;") + && methodDef.name == "onFinishInflate" }, ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/privacy/RemoveTrackingQueryParameterPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/privacy/RemoveTrackingQueryParameterPatch.kt index c811a6bfb..28404a8f4 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/privacy/RemoveTrackingQueryParameterPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/privacy/RemoveTrackingQueryParameterPatch.kt @@ -35,16 +35,20 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object RemoveTrackingQueryParameterPatch : BytecodePatch( - setOf(CopyTextFingerprint, SystemShareSheetFingerprint, YouTubeShareSheetFingerprint), + setOf(CopyTextFingerprint, SystemShareSheetFingerprint, YouTubeShareSheetFingerprint) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/RemoveTrackingQueryParameterPatch;" @@ -52,12 +56,12 @@ object RemoveTrackingQueryParameterPatch : BytecodePatch( AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.MISC.addPreferences( - SwitchPreference("revanced_remove_tracking_query_parameter"), + SwitchPreference("revanced_remove_tracking_query_parameter") ) fun MethodFingerprint.hook( getInsertIndex: PatternScanResult.() -> Int, - getUrlRegister: MutableMethod.(insertIndex: Int) -> Int, + getUrlRegister: MutableMethod.(insertIndex: Int) -> Int ) = result?.let { val insertIndex = it.scanResult.patternScanResult!!.getInsertIndex() val urlRegister = it.mutableMethod.getUrlRegister(insertIndex) @@ -67,16 +71,19 @@ object RemoveTrackingQueryParameterPatch : BytecodePatch( """ invoke-static {v$urlRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->sanitize(Ljava/lang/String;)Ljava/lang/String; move-result-object v$urlRegister - """, + """ ) } ?: throw exception // Native YouTube share sheet. - YouTubeShareSheetFingerprint.hook(getInsertIndex = { startIndex + 1 }) { insertIndex -> getInstruction(insertIndex - 1).registerA } + YouTubeShareSheetFingerprint.hook(getInsertIndex = { startIndex + 1 }) + { insertIndex -> getInstruction(insertIndex - 1).registerA } // Native system share sheet. - SystemShareSheetFingerprint.hook(getInsertIndex = { endIndex }) { insertIndex -> getInstruction(insertIndex - 1).registerA } + SystemShareSheetFingerprint.hook(getInsertIndex = { endIndex }) + { insertIndex -> getInstruction(insertIndex - 1).registerA } - CopyTextFingerprint.hook(getInsertIndex = { startIndex + 2 }) { insertIndex -> getInstruction(insertIndex - 2).registerA } + CopyTextFingerprint.hook(getInsertIndex = { startIndex + 2 }) + { insertIndex -> getInstruction(insertIndex - 2).registerA } } -} +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/HDRBrightnessPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/HDRBrightnessPatch.kt index 1c5f61d2e..31141a311 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/HDRBrightnessPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/hdrbrightness/HDRBrightnessPatch.kt @@ -10,12 +10,13 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.settings.SettingsPatch import app.revanced.patches.youtube.video.hdrbrightness.fingerprints.HDRBrightnessFingerprint +import app.revanced.util.exception import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.FieldReference +@Deprecated("Patch is obsolete and the hooked code is no longer present in 19.09+") @Patch( - name = "HDR auto brightness", description = "Adds an option to make the brightness of HDR videos follow the system default.", dependencies = [IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class], compatiblePackages = [ @@ -32,12 +33,16 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + // 19.09+ is dramatically different and the patched code is not present. + ] + ) + ] ) @Suppress("unused") object HDRBrightnessPatch : BytecodePatch( @@ -46,27 +51,31 @@ object HDRBrightnessPatch : BytecodePatch( override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) + if (HDRBrightnessFingerprint.result == null) throw HDRBrightnessFingerprint.exception + SettingsPatch.PreferenceScreen.VIDEO.addPreferences( SwitchPreference("revanced_hdr_auto_brightness"), ) - val method = HDRBrightnessFingerprint.result!!.mutableMethod - - method.implementation!!.instructions.filter { instruction -> - val fieldReference = (instruction as? ReferenceInstruction)?.reference as? FieldReference - fieldReference?.let { it.name == "screenBrightness" } == true - }.forEach { instruction -> - val brightnessRegisterIndex = method.implementation!!.instructions.indexOf(instruction) - val register = (instruction as TwoRegisterInstruction).registerA - - val insertIndex = brightnessRegisterIndex + 1 - method.addInstructions( - insertIndex, - """ - invoke-static {v$register}, Lapp/revanced/integrations/youtube/patches/HDRAutoBrightnessPatch;->getHDRBrightness(F)F - move-result v$register - """, - ) - } + // FIXME + // One of the changes made here effectively does nothing: + // It calls getHDRBrightness() and ignores the results. + HDRBrightnessFingerprint.result?.mutableMethod?.apply { + implementation!!.instructions.filter { instruction -> + ((instruction as? ReferenceInstruction)?.reference as? FieldReference) + ?.name == "screenBrightness" + }.forEach { instruction -> + val brightnessRegisterIndex = implementation!!.instructions.indexOf(instruction) + val register = (instruction as TwoRegisterInstruction).registerA + val insertIndex = brightnessRegisterIndex + 1 + addInstructions( + insertIndex, + """ + invoke-static {v$register}, Lapp/revanced/integrations/youtube/patches/HDRAutoBrightnessPatch;->getHDRBrightness(F)F + move-result v$register + """, + ) + } + } ?: throw HDRBrightnessFingerprint.exception } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt index 16dab1f43..858d30b14 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt @@ -30,30 +30,33 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference IntegrationsPatch::class, VideoInformationPatch::class, SettingsPatch::class, - AddResourcesPatch::class, + AddResourcesPatch::class ], compatiblePackages = [ CompatiblePackage( - "com.google.android.youtube", - [ + "com.google.android.youtube", [ "18.48.39", "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object RememberVideoQualityPatch : BytecodePatch( setOf( VideoQualitySetterFingerprint, VideoQualityItemOnClickParentFingerprint, - NewVideoQualityChangedFingerprint, - ), + NewVideoQualityChangedFingerprint + ) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/playback/quality/RememberVideoQualityPatch;" @@ -67,14 +70,14 @@ object RememberVideoQualityPatch : BytecodePatch( key = "revanced_video_quality_default_wifi", summaryKey = null, entriesKey = "revanced_video_quality_default_entries", - entryValuesKey = "revanced_video_quality_default_entry_values", + entryValuesKey = "revanced_video_quality_default_entry_values" ), ListPreference( key = "revanced_video_quality_default_mobile", summaryKey = null, entriesKey = "revanced_video_quality_default_entries", - entryValuesKey = "revanced_video_quality_default_entry_values", - ), + entryValuesKey = "revanced_video_quality_default_entry_values" + ) ) /* @@ -86,11 +89,11 @@ object RememberVideoQualityPatch : BytecodePatch( */ VideoInformationPatch.onCreateHook(INTEGRATIONS_CLASS_DESCRIPTOR, "newVideoStarted") + // Inject a call to set the remembered quality once a video loads. VideoQualitySetterFingerprint.result?.also { - if (!SetQualityByIndexMethodClassFieldReferenceFingerprint.resolve(context, it.classDef)) { + if (!SetQualityByIndexMethodClassFieldReferenceFingerprint.resolve(context, it.classDef)) throw PatchException("Could not resolve fingerprint to find setQualityByIndex method") - } }?.let { // This instruction refers to the field with the type that contains the setQualityByIndex method. val instructions = SetQualityByIndexMethodClassFieldReferenceFingerprint.result!! @@ -133,6 +136,7 @@ object RememberVideoQualityPatch : BytecodePatch( ) } ?: throw VideoQualitySetterFingerprint.exception + // Inject a call to remember the selected quality. VideoQualityItemOnClickParentFingerprint.result?.let { val onItemClickMethod = it.mutableClass.methods.find { method -> method.name == "onItemClick" } @@ -142,11 +146,12 @@ object RememberVideoQualityPatch : BytecodePatch( addInstruction( 0, - "invoke-static {p$listItemIndexParameter}, $INTEGRATIONS_CLASS_DESCRIPTOR->userChangedQuality(I)V", + "invoke-static {p$listItemIndexParameter}, $INTEGRATIONS_CLASS_DESCRIPTOR->userChangedQuality(I)V" ) } ?: throw PatchException("Failed to find onItemClick method") } ?: throw VideoQualityItemOnClickParentFingerprint.exception + // Remember video quality if not using old layout menu. NewVideoQualityChangedFingerprint.result?.apply { mutableMethod.apply { @@ -155,7 +160,7 @@ object RememberVideoQualityPatch : BytecodePatch( addInstruction( index + 1, - "invoke-static {v$qualityRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->userChangedQualityInNewFlyout(I)V", + "invoke-static {v$qualityRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->userChangedQualityInNewFlyout(I)V" ) } } ?: throw NewVideoQualityChangedFingerprint.exception diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/speed/PlaybackSpeedPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/PlaybackSpeedPatch.kt index bbaf5371e..f8e9330a5 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/speed/PlaybackSpeedPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/speed/PlaybackSpeedPatch.kt @@ -19,9 +19,13 @@ import app.revanced.patches.youtube.video.speed.remember.RememberPlaybackSpeedPa "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" ], ), ], diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuPatch.kt index d9363c615..25b01b1ab 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/RestoreOldVideoQualityMenuPatch.kt @@ -19,7 +19,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction IntegrationsPatch::class, RestoreOldVideoQualityMenuResourcePatch::class, LithoFilterPatch::class, - RecyclerViewTreeHookPatch::class, + RecyclerViewTreeHookPatch::class ], compatiblePackages = [ CompatiblePackage( @@ -35,22 +35,26 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction "18.49.37", "19.01.34", "19.02.39", - "19.03.35", "19.03.36", - "19.04.37", - ], - ), - ], + "19.04.38", + "19.05.36", + "19.06.39", + "19.07.40", + "19.08.36", + "19.09.37" + ] + ) + ] ) @Suppress("unused") object RestoreOldVideoQualityMenuPatch : BytecodePatch( - setOf(VideoQualityMenuViewInflateFingerprint), + setOf(VideoQualityMenuViewInflateFingerprint) ) { private const val FILTER_CLASS_DESCRIPTOR = - "Lapp/revanced/integrations/youtube/patches/components/VideoQualityMenuFilterPatch;" + "Lapp/revanced/integrations/youtube/patches/components/VideoQualityMenuFilterPatch;" private const val INTEGRATIONS_CLASS_DESCRIPTOR = - "Lapp/revanced/integrations/youtube/patches/playback/quality/RestoreOldVideoQualityMenuPatch;" + "Lapp/revanced/integrations/youtube/patches/playback/quality/RestoreOldVideoQualityMenuPatch;" override fun execute(context: BytecodeContext) { // region Patch for the old type of the video quality menu. @@ -64,8 +68,8 @@ object RestoreOldVideoQualityMenuPatch : BytecodePatch( addInstruction( checkCastIndex + 1, "invoke-static { v$listViewRegister }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->" + - "showOldVideoQualityMenu(Landroid/widget/ListView;)V", + "$INTEGRATIONS_CLASS_DESCRIPTOR->" + + "showOldVideoQualityMenu(Landroid/widget/ListView;)V" ) } } @@ -81,4 +85,4 @@ object RestoreOldVideoQualityMenuPatch : BytecodePatch( // endregion } -} +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/util/BytecodeUtils.kt b/src/main/kotlin/app/revanced/util/BytecodeUtils.kt index 51dbd145e..542dddd07 100644 --- a/src/main/kotlin/app/revanced/util/BytecodeUtils.kt +++ b/src/main/kotlin/app/revanced/util/BytecodeUtils.kt @@ -15,6 +15,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction import com.android.tools.smali.dexlib2.iface.reference.Reference import com.android.tools.smali.dexlib2.util.MethodUtil + +fun MethodFingerprint.resultOrThrow() = result ?: throw exception + /** * The [PatchException] of failing to resolve a [MethodFingerprint]. * diff --git a/src/main/resources/addresources/values/arrays.xml b/src/main/resources/addresources/values/arrays.xml index 064dcd05b..5fad2d884 100644 --- a/src/main/resources/addresources/values/arrays.xml +++ b/src/main/resources/addresources/values/arrays.xml @@ -44,15 +44,28 @@ + + @string/revanced_alt_thumbnail_options_entry_1 + @string/revanced_alt_thumbnail_options_entry_2 + @string/revanced_alt_thumbnail_options_entry_3 + @string/revanced_alt_thumbnail_options_entry_4 + + + + ORIGINAL + DEARROW + DEARROW_STILL_IMAGES + STILL_IMAGES + @string/revanced_alt_thumbnail_stills_time_entry_1 @string/revanced_alt_thumbnail_stills_time_entry_2 @string/revanced_alt_thumbnail_stills_time_entry_3 - 1 - 2 - 3 + BEGINNING + MIDDLE + END diff --git a/src/main/resources/addresources/values/strings.xml b/src/main/resources/addresources/values/strings.xml index c7461f621..d7ac91cf7 100644 --- a/src/main/resources/addresources/values/strings.xml +++ b/src/main/resources/addresources/values/strings.xml @@ -167,9 +167,24 @@ Custom filter is disabled Custom filter List of component path builder strings to filter separated by new line - Invalid custom filter (must be ASCII only): %s Invalid custom filter: %s - Custom filter reset to default + Hide keyword content + Hide search and feed videos using keyword filters + Hide home videos by keywords + Videos in the home tab are filtered by keywords + Videos in the home tab are not filtered by keywords + Hide subscription videos by keywords + Videos in the subscriptions tab are filtered by keywords + Videos in the subscriptions tab are not filtered by keywords + Hide search results by keywords + Search results are filtered by keywords + Search results are not filtered by keywords + Keywords to hide + Keywords and phrases to hide, separated by new lines\n\nWords with uppercase letters in the middle must be entered with the casing (ie: iPhone, TikTok, LeBlanc) + About keyword filtering + Home/Subscription/Search results are filtered to hide content that matches keyword phrases\n\nLimitations\n• Some Shorts may not be hidden\n• Some UI components may not be hidden\n• Searching for a keyword may show no results + Invalid keyword. Cannot use: \'%s\' as a filter + Invalid keyword. \'%s\' is less than %s characters Hide general ads @@ -199,6 +214,7 @@ Hide merchandise banners Merchandise banners are hidden Merchandise banners are shown + Failed to hide full-screen ad. Disabling to prevent issues Hide YouTube Premium promotions @@ -226,12 +242,15 @@ Dialog will be shown This does not bypass the age restriction. It just accepts it automatically. - + External downloads Settings for using an external downloader Show external download button Download button shown in player Download button not shown in player + Override download action button + Download button opens your external downloader + Download button opens the native in-app downloader Downloader package name Package name of your installed external downloader app, such as NewPipe or Seal %s is not installed. Please install it. @@ -460,9 +479,15 @@ Thumbnail seekbar is shown - Hide Shorts in feed - Shorts are hidden - Shorts are shown + Hide Shorts in home feed + Shorts in home feed are hidden + Shorts in home feed are shown + Hide Shorts in subscription feed + Shorts in subscription feed are hidden + Shorts in subscription feed are shown + Hide Shorts in search results + Shorts in search results are hidden + Shorts in search results are shown Hide join button Join button is hidden Join button is shown @@ -475,6 +500,12 @@ Hide thanks button Thanks button is hidden Thanks button is shown + Hide like button + Like button is hidden + Like button is shown + Hide dislike button + Dislike button is hidden + Dislike button is shown Hide comments button Comments button is hidden Comments button is shown @@ -490,6 +521,15 @@ Hide channel bar Channel bar is hidden Channel bar is shown + Hide Shorts video title + Title is hidden + Title is shown + Hide sound metadata label + Label is hidden + Label is shown + Hide full video link label + Label is hidden + Label is shown Hide sound button Sound button is hidden Sound button is shown @@ -807,33 +847,31 @@ Invalid seekbar color value. Using default value. - Thumbnails in use - Enable DeArrow thumbnails - Using DeArrow thumbnails - Not using DeArrow thumbnails + Home tab + Subscription tab + You tab + Player playlists, recommendations + Search results + Original thumbnails + DeArrow & Original thumbnails + DeArrow & Still captures + Still captures + DeArrow + DeArrow provides crowd-sourced thumbnails for YouTube videos. These thumbnails are often more relevant than those provided by YouTube\n\nIf enabled, video URLs will be sent to the API server and no other data is sent. If a video does not have DeArrow thumbnails, then the original or still captures are shown\n\nTap here to learn more about DeArrow Show a toast if API is not available Toast is shown if DeArrow is not available Toast is not shown if DeArrow is not available DeArrow API endpoint - The URL of the DeArrow thumbnail cache endpoint. Do not change this unless you know what you\'re doing - About DeArrow - DeArrow provides crowd-sourced thumbnails for YouTube videos. These thumbnails are often more relevant than those provided by YouTube. If enabled, video URLs will be sent to the API server and no other data is sent\n\nTap here to learn more about DeArrow - Enable still video captures - Using YouTube still video captures - Not using YouTube still video captures - Video time to take the still from - Beginning of video - Middle of video - End of video + The URL of the DeArrow thumbnail cache endpoint + Still video captures + Still captures are taken from the beginning/middle/end of each video. These images are built into YouTube and no external API is used Use fast still captures Using medium quality still captures. Thumbnails will load faster, but live streams, unreleased, or very old videos may show blank thumbnails Using high quality still captures - About still video captures - Still captures are taken from the beginning/middle/end of each video. These images are built into YouTube and no external API is used - Showing original YouTube thumbnails - Showing still video captures - Showing DeArrow thumbnails. If a video has no DeArrow thumbnails then the original YouTube thumbnails are shown - Showing DeArrow thumbnails. If a video has no DeArrow thumbnails then still video captures are shown + Video time to take still captures from + Beginning of video + Middle of video + End of video DeArrow temporarily not available (status code: %s) DeArrow temporarily not available