From b8858f7853ee3453ab9e9f6fc068d80eeae55c92 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 15 Feb 2024 23:48:44 +0400 Subject: [PATCH 01/26] feat(YouTube): Add `Hide keyword content` patch --- api/revanced-patches.api | 6 ++ .../hide/keyword/HideKeywordContentPatch.kt | 57 +++++++++++++++++++ .../resources/addresources/values/strings.xml | 12 ++++ 3 files changed, 75 insertions(+) create mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hide/keyword/HideKeywordContentPatch.kt diff --git a/api/revanced-patches.api b/api/revanced-patches.api index 4e1ad810a5..4d325dac79 100644 --- a/api/revanced-patches.api +++ b/api/revanced-patches.api @@ -1350,6 +1350,12 @@ public final class app/revanced/patches/youtube/layout/hide/infocards/HideInfoca public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V } +public final class app/revanced/patches/youtube/layout/hide/keyword/HideKeywordContentPatch : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/youtube/layout/hide/keyword/HideKeywordContentPatch; + 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/youtube/layout/hide/loadmorebutton/HideLoadMoreButtonPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/youtube/layout/hide/loadmorebutton/HideLoadMoreButtonPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/keyword/HideKeywordContentPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/keyword/HideKeywordContentPatch.kt new file mode 100644 index 0000000000..ed76a910ca --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/keyword/HideKeywordContentPatch.kt @@ -0,0 +1,57 @@ +package app.revanced.patches.youtube.layout.hide.keyword + +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.all.misc.resources.AddResourcesPatch +import app.revanced.patches.shared.misc.settings.preference.InputType +import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen +import app.revanced.patches.shared.misc.settings.preference.SwitchPreference +import app.revanced.patches.shared.misc.settings.preference.TextPreference +import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch +import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch +import app.revanced.patches.youtube.misc.settings.SettingsPatch + +@Patch( + name = "Hide keyword content", + description = "Adds options to hide home feed or search results based on keywords", + dependencies = [IntegrationsPatch::class, SettingsPatch::class, LithoFilterPatch::class], + compatiblePackages = [ + CompatiblePackage( + "com.google.android.youtube", [ + "18.43.45", + "18.44.41", + "18.45.43", + "18.48.39", + "18.49.37", + "19.01.34", + "19.02.39", + "19.03.35", + "19.03.36", + "19.04.37" + ] + ) + ] +) +@Suppress("unused") +object HideKeywordContentPatch : BytecodePatch(emptySet()) { + private const val FILTER_CLASS_DESCRIPTOR = + "Lapp/revanced/integrations/youtube/patches/components/HideKeywordContentFilter;" + + override fun execute(context: BytecodeContext) { + AddResourcesPatch(this::class) + + SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( + PreferenceScreen( + key = "revanced_hide_keyword_content_preference_screen", + preferences = setOf( + SwitchPreference("revanced_hide_keyword_content"), + TextPreference("revanced_hide_keyword_content_phrases", inputType = InputType.TEXT_MULTI_LINE), + ), + ) + ) + + LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR) + } +} diff --git a/src/main/resources/addresources/values/strings.xml b/src/main/resources/addresources/values/strings.xml index c473143626..051930552e 100644 --- a/src/main/resources/addresources/values/strings.xml +++ b/src/main/resources/addresources/values/strings.xml @@ -431,6 +431,18 @@ Microphone button hidden Microphone button shown + + Hide keyword content + Hide home/search result videos with keyword filters + Enable keyword filtering + Home/search is filtered to hide content matching keyword phrases\n\nLimitations\n• Some UI elements may not be hidden\n• Searching for a keyword may give no search results\n• Some Shorts may not be hidden + Home/search results are not filtered + Keywords to hide + Keyword and phrases to hide, separated by new lines\n\nKeywords specified here automatically include some uppercase and lowercase variations, but some keywords require entering the exact casing (ie: \'LeBlanc\', \'Van Der Berg\', etc) + Invalid keyword phrase (must be ASCII only): %s + Invalid keyword length (must be at least %s characters): %s + Keywords reset to default + Disable ambient mode in fullscreen Ambient mode disabled From 9cd5a63422c573688acca53dd631bdf6a64ca050 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Fri, 8 Mar 2024 11:13:06 +0400 Subject: [PATCH 02/26] refactor: move code into `HideLayoutComponents` --- api/revanced-patches.api | 6 -- .../hide/general/HideLayoutComponentsPatch.kt | 13 +++++ .../hide/keyword/HideKeywordContentPatch.kt | 57 ------------------- .../resources/addresources/values/strings.xml | 22 ++++--- 4 files changed, 23 insertions(+), 75 deletions(-) delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hide/keyword/HideKeywordContentPatch.kt diff --git a/api/revanced-patches.api b/api/revanced-patches.api index 4d325dac79..4e1ad810a5 100644 --- a/api/revanced-patches.api +++ b/api/revanced-patches.api @@ -1350,12 +1350,6 @@ public final class app/revanced/patches/youtube/layout/hide/infocards/HideInfoca public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V } -public final class app/revanced/patches/youtube/layout/hide/keyword/HideKeywordContentPatch : app/revanced/patcher/patch/BytecodePatch { - public static final field INSTANCE Lapp/revanced/patches/youtube/layout/hide/keyword/HideKeywordContentPatch; - 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/youtube/layout/hide/loadmorebutton/HideLoadMoreButtonPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/youtube/layout/hide/loadmorebutton/HideLoadMoreButtonPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V 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 f72d80a324..61e00eb330 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 @@ -65,6 +65,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/HideKeywordContentFilter;" override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) @@ -113,6 +115,16 @@ object HideLayoutComponentsPatch : BytecodePatch( SwitchPreference("revanced_hide_search_result_shelf_header"), ) + SettingsPatch.PreferenceScreen.FEED.addPreferences( + PreferenceScreen( + key = "revanced_hide_keyword_content_preference_screen", + preferences = setOf( + SwitchPreference("revanced_hide_keyword_content"), + TextPreference("revanced_hide_keyword_content_phrases", inputType = InputType.TEXT_MULTI_LINE), + ), + ) + ) + SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences( SwitchPreference("revanced_hide_gray_separator"), PreferenceScreen( @@ -132,6 +144,7 @@ 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 diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/keyword/HideKeywordContentPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/keyword/HideKeywordContentPatch.kt deleted file mode 100644 index ed76a910ca..0000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/keyword/HideKeywordContentPatch.kt +++ /dev/null @@ -1,57 +0,0 @@ -package app.revanced.patches.youtube.layout.hide.keyword - -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.all.misc.resources.AddResourcesPatch -import app.revanced.patches.shared.misc.settings.preference.InputType -import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen -import app.revanced.patches.shared.misc.settings.preference.SwitchPreference -import app.revanced.patches.shared.misc.settings.preference.TextPreference -import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch -import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch -import app.revanced.patches.youtube.misc.settings.SettingsPatch - -@Patch( - name = "Hide keyword content", - description = "Adds options to hide home feed or search results based on keywords", - dependencies = [IntegrationsPatch::class, SettingsPatch::class, LithoFilterPatch::class], - compatiblePackages = [ - CompatiblePackage( - "com.google.android.youtube", [ - "18.43.45", - "18.44.41", - "18.45.43", - "18.48.39", - "18.49.37", - "19.01.34", - "19.02.39", - "19.03.35", - "19.03.36", - "19.04.37" - ] - ) - ] -) -@Suppress("unused") -object HideKeywordContentPatch : BytecodePatch(emptySet()) { - private const val FILTER_CLASS_DESCRIPTOR = - "Lapp/revanced/integrations/youtube/patches/components/HideKeywordContentFilter;" - - override fun execute(context: BytecodeContext) { - AddResourcesPatch(this::class) - - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - PreferenceScreen( - key = "revanced_hide_keyword_content_preference_screen", - preferences = setOf( - SwitchPreference("revanced_hide_keyword_content"), - TextPreference("revanced_hide_keyword_content_phrases", inputType = InputType.TEXT_MULTI_LINE), - ), - ) - ) - - LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR) - } -} diff --git a/src/main/resources/addresources/values/strings.xml b/src/main/resources/addresources/values/strings.xml index 051930552e..da09bdd000 100644 --- a/src/main/resources/addresources/values/strings.xml +++ b/src/main/resources/addresources/values/strings.xml @@ -170,6 +170,16 @@ Invalid custom filter (must be ASCII only): %s Invalid custom filter: %s Custom filter reset to default + Hide keyword content + Hide feed and search result videos using keyword filters + Enable keyword filtering + Feed/search is filtered to hide content that matches keyword phrases\n\nLimitations\n• Some UI elements may not be hidden\n• Some Shorts may not be hidden\n• Searching for a keyword may show no results + Feed/search results are not filtered + Keywords to hide + Keywords and phrases to hide, separated by new lines.\n\nText specified here automatically include some uppercase and lowercase variations, but some text requires entering the exact casing (ie: LeBlanc, John Doe, etc) + Invalid keyword phrase (must be ASCII only): %s + Invalid keyword length (must be at least %s characters): %s + Keywords reset to default Hide general ads @@ -431,18 +441,6 @@ Microphone button hidden Microphone button shown - - Hide keyword content - Hide home/search result videos with keyword filters - Enable keyword filtering - Home/search is filtered to hide content matching keyword phrases\n\nLimitations\n• Some UI elements may not be hidden\n• Searching for a keyword may give no search results\n• Some Shorts may not be hidden - Home/search results are not filtered - Keywords to hide - Keyword and phrases to hide, separated by new lines\n\nKeywords specified here automatically include some uppercase and lowercase variations, but some keywords require entering the exact casing (ie: \'LeBlanc\', \'Van Der Berg\', etc) - Invalid keyword phrase (must be ASCII only): %s - Invalid keyword length (must be at least %s characters): %s - Keywords reset to default - Disable ambient mode in fullscreen Ambient mode disabled From cc19666b5803fb1da08c349b7a01b12cb7988cfb Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Fri, 8 Mar 2024 17:29:12 +0400 Subject: [PATCH 03/26] feat: Support unicode keyword and custom filters --- src/main/resources/addresources/values/strings.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/resources/addresources/values/strings.xml b/src/main/resources/addresources/values/strings.xml index da09bdd000..b5003b08eb 100644 --- a/src/main/resources/addresources/values/strings.xml +++ b/src/main/resources/addresources/values/strings.xml @@ -167,7 +167,6 @@ 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 @@ -177,7 +176,6 @@ Feed/search results are not filtered Keywords to hide Keywords and phrases to hide, separated by new lines.\n\nText specified here automatically include some uppercase and lowercase variations, but some text requires entering the exact casing (ie: LeBlanc, John Doe, etc) - Invalid keyword phrase (must be ASCII only): %s Invalid keyword length (must be at least %s characters): %s Keywords reset to default From 2c65188684c83eca87e7968bab1f443341a9b966 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Fri, 8 Mar 2024 18:40:39 +0400 Subject: [PATCH 04/26] fix: Use unsorted --- .../youtube/layout/hide/general/HideLayoutComponentsPatch.kt | 1 + 1 file changed, 1 insertion(+) 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 61e00eb330..75f1ebf7b5 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 @@ -118,6 +118,7 @@ object HideLayoutComponentsPatch : BytecodePatch( SettingsPatch.PreferenceScreen.FEED.addPreferences( PreferenceScreen( key = "revanced_hide_keyword_content_preference_screen", + sorting = Sorting.UNSORTED, preferences = setOf( SwitchPreference("revanced_hide_keyword_content"), TextPreference("revanced_hide_keyword_content_phrases", inputType = InputType.TEXT_MULTI_LINE), From f6bc93650f1301cf4f0a301f847b2354d46a1bc3 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Fri, 8 Mar 2024 21:20:15 +0400 Subject: [PATCH 05/26] adjust text --- src/main/resources/addresources/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/addresources/values/strings.xml b/src/main/resources/addresources/values/strings.xml index b5003b08eb..a8c42b0561 100644 --- a/src/main/resources/addresources/values/strings.xml +++ b/src/main/resources/addresources/values/strings.xml @@ -175,7 +175,7 @@ Feed/search is filtered to hide content that matches keyword phrases\n\nLimitations\n• Some UI elements may not be hidden\n• Some Shorts may not be hidden\n• Searching for a keyword may show no results Feed/search results are not filtered Keywords to hide - Keywords and phrases to hide, separated by new lines.\n\nText specified here automatically include some uppercase and lowercase variations, but some text requires entering the exact casing (ie: LeBlanc, John Doe, etc) + Keywords and phrases to hide, separated by new lines\n\nText specified here automatically include some uppercase and lowercase variations, but some text requires entering exact casing (ie: LeBlanc, John Doe) Invalid keyword length (must be at least %s characters): %s Keywords reset to default From bc25b65dd375d713ca34669ebd846b75816bcc6d Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sat, 9 Mar 2024 17:37:23 +0400 Subject: [PATCH 06/26] fix: Do not reset keywords or custom filter. Show a toast and leave as-is for the user to fix. --- src/main/resources/addresources/values/strings.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/resources/addresources/values/strings.xml b/src/main/resources/addresources/values/strings.xml index a8c42b0561..b7904ab37d 100644 --- a/src/main/resources/addresources/values/strings.xml +++ b/src/main/resources/addresources/values/strings.xml @@ -168,7 +168,6 @@ Custom filter List of component path builder strings to filter separated by new line Invalid custom filter: %s - Custom filter reset to default Hide keyword content Hide feed and search result videos using keyword filters Enable keyword filtering @@ -177,7 +176,6 @@ Keywords to hide Keywords and phrases to hide, separated by new lines\n\nText specified here automatically include some uppercase and lowercase variations, but some text requires entering exact casing (ie: LeBlanc, John Doe) Invalid keyword length (must be at least %s characters): %s - Keywords reset to default Hide general ads From dfc8e886283aae840ff76a0c262df48fb9af542c Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sat, 9 Mar 2024 18:24:37 +0400 Subject: [PATCH 07/26] fix: Automatically filter capitalized first letter of each sentence. --- src/main/resources/addresources/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/addresources/values/strings.xml b/src/main/resources/addresources/values/strings.xml index b7904ab37d..1c4c2638ee 100644 --- a/src/main/resources/addresources/values/strings.xml +++ b/src/main/resources/addresources/values/strings.xml @@ -174,7 +174,7 @@ Feed/search is filtered to hide content that matches keyword phrases\n\nLimitations\n• Some UI elements may not be hidden\n• Some Shorts may not be hidden\n• Searching for a keyword may show no results Feed/search results are not filtered Keywords to hide - Keywords and phrases to hide, separated by new lines\n\nText specified here automatically include some uppercase and lowercase variations, but some text requires entering exact casing (ie: LeBlanc, John Doe) + Keywords and phrases to hide, separated by new lines\n\nKeywords or phrases with mix casing must include the casing (ie: LeBlanc, DeAndre, TikTok) Invalid keyword length (must be at least %s characters): %s From 86f24c82c0b56f043b348e66708850e0dac81c6f Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sat, 9 Mar 2024 18:33:41 +0400 Subject: [PATCH 08/26] refactor: Rename class --- .../youtube/layout/hide/general/HideLayoutComponentsPatch.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 75f1ebf7b5..e5cc588800 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 @@ -66,7 +66,7 @@ object HideLayoutComponentsPatch : BytecodePatch( 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/HideKeywordContentFilter;" + "Lapp/revanced/integrations/youtube/patches/components/KeywordContentFilter;" override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) From e82f6a2de7ae5b47a1c1f214e06e35c046167ac4 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sun, 10 Mar 2024 19:40:40 +0400 Subject: [PATCH 09/26] fix: adjust settings text --- src/main/resources/addresources/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/addresources/values/strings.xml b/src/main/resources/addresources/values/strings.xml index 1c4c2638ee..5f7558a4fa 100644 --- a/src/main/resources/addresources/values/strings.xml +++ b/src/main/resources/addresources/values/strings.xml @@ -172,9 +172,9 @@ Hide feed and search result videos using keyword filters Enable keyword filtering Feed/search is filtered to hide content that matches keyword phrases\n\nLimitations\n• Some UI elements may not be hidden\n• Some Shorts may not be hidden\n• Searching for a keyword may show no results - Feed/search results are not filtered + Feed/search results are not filtered by keywords Keywords to hide - Keywords and phrases to hide, separated by new lines\n\nKeywords or phrases with mix casing must include the casing (ie: LeBlanc, DeAndre, TikTok) + Keywords and phrases to hide, separated by new lines\n\nWords with unusual upper/lower case usage must include the casing (ie: LeBlanc, DeAndre, TikTok) Invalid keyword length (must be at least %s characters): %s From d89490be3347048406044be50c82b4ec1b325bae Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Mon, 11 Mar 2024 17:35:03 +0400 Subject: [PATCH 10/26] fix: adjust settings text --- src/main/resources/addresources/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/addresources/values/strings.xml b/src/main/resources/addresources/values/strings.xml index 5f7558a4fa..12db801a4d 100644 --- a/src/main/resources/addresources/values/strings.xml +++ b/src/main/resources/addresources/values/strings.xml @@ -171,10 +171,10 @@ Hide keyword content Hide feed and search result videos using keyword filters Enable keyword filtering - Feed/search is filtered to hide content that matches keyword phrases\n\nLimitations\n• Some UI elements may not be hidden\n• Some Shorts may not be hidden\n• Searching for a keyword may show no results + Feed/search is filtered to hide content that matches keyword phrases\n\nLimitations\n• Some Shorts may not be hidden\n• Some UI elements may not be hidden\n• Searching for a keyword may show no results Feed/search results are not filtered by keywords Keywords to hide - Keywords and phrases to hide, separated by new lines\n\nWords with unusual upper/lower case usage must include the casing (ie: LeBlanc, DeAndre, TikTok) + 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) Invalid keyword length (must be at least %s characters): %s From 944b7550cb82adffda499ede9df07cdc4cba721d Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 14 Mar 2024 13:02:45 +0400 Subject: [PATCH 11/26] feat: Selective filtering of search/home/subscriptions --- .../navigation/NavigationButtonsPatch.kt | 47 ++++++++++++++----- .../ResolvePivotBarFingerprintsPatch.kt | 13 +++-- .../ActionBarSearchResultsFingerprint.kt | 13 +++++ .../navigation/utils/InjectionUtils.kt | 2 +- .../hide/general/HideLayoutComponentsPatch.kt | 14 ++++-- .../resources/addresources/values/strings.xml | 18 +++++-- 6 files changed, 82 insertions(+), 25 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/ActionBarSearchResultsFingerprint.kt 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 94e67f73b3..117aad8134 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 @@ -1,6 +1,7 @@ package app.revanced.patches.youtube.layout.buttons.navigation 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.patch.BytecodePatch @@ -16,8 +17,13 @@ import app.revanced.patches.youtube.layout.buttons.navigation.utils.InjectionUti import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.settings.SettingsPatch import app.revanced.util.exception +import app.revanced.util.getReference +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 +import com.android.tools.smali.dexlib2.iface.reference.MethodReference +// TODO: break this patch apart so other patches can check what tab is active (without depending on this patch). @Patch( name = "Navigation buttons", description = "Adds options to hide and change navigation buttons (such as the Shorts button).", @@ -54,7 +60,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction ) @Suppress("unused") object NavigationButtonsPatch : BytecodePatch( - setOf(AddCreateButtonViewFingerprint), + setOf(AddCreateButtonViewFingerprint, ActionBarSearchResultsFingerprint), ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/NavigationButtonsPatch;" @@ -106,17 +112,17 @@ object NavigationButtonsPatch : BytecodePatch( * Inject hooks */ - val enumHook = "sput-object v$REGISTER_TEMPLATE_REPLACEMENT, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->lastNavigationButton:Ljava/lang/Enum;" + val enumHook = "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + + "$INTEGRATIONS_CLASS_DESCRIPTOR->setLastAppNavigationEnum(Ljava/lang/Enum;)V" val buttonHook = "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->hideButton(Landroid/view/View;)V" + "$INTEGRATIONS_CLASS_DESCRIPTOR->navigationTabLoaded(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) + initializeButtonsResult.mutableMethod.injectHook(insertIndex, hook) } /* @@ -154,14 +160,31 @@ object NavigationButtonsPatch : BytecodePatch( PivotBarCreateButtonViewFingerprint.result!!.apply { val insertIndex = scanResult.patternScanResult!!.endIndex + mutableMethod.injectHook( + insertIndex, + "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + + "$INTEGRATIONS_CLASS_DESCRIPTOR->createTabLoaded(Landroid/view/View;)V" + ) + } - /* - * Inject hooks - */ - val hook = "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->hideCreateButton(Landroid/view/View;)V" + /** + * Search bar TextView + */ - mutableMethod.injectHook(hook, insertIndex) - } + // 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.result?.mutableMethod?.apply { + val instructionIndex = implementation!!.instructions.indexOfFirst { + it.opcode == Opcode.INVOKE_VIRTUAL && + it.getReference()?.name == "setLayoutDirection" + } + val register = getInstruction(instructionIndex).registerC + addInstruction( + instructionIndex, + "invoke-static { v$register }, " + + "$INTEGRATIONS_CLASS_DESCRIPTOR->searchBarResultsViewLoaded(Landroid/view/View;)V" + ) + } ?: ActionBarSearchResultsFingerprint.exception } } 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 index eacab72b45..3a11960b50 100644 --- 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 @@ -1,13 +1,12 @@ package app.revanced.patches.youtube.layout.buttons.navigation -import app.revanced.util.exception 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.", @@ -17,11 +16,17 @@ internal object ResolvePivotBarFingerprintsPatch : BytecodePatch( setOf(PivotBarConstructorFingerprint) ) { internal var imageOnlyTabResourceId: Long = -1 + internal var actionBarSearchResultsViewMicId: 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") + imageOnlyTabResourceId = ResourceMappingPatch.resourceMappings.single { + it.type == "layout" && it.name == "image_only_tab" + }.id + + actionBarSearchResultsViewMicId = ResourceMappingPatch.resourceMappings.single { + it.type == "layout" && it.name == "action_bar_search_results_view_mic" + }.id PivotBarConstructorFingerprint.result?.let { // Resolve InitializeButtonsFingerprint on the class of the method diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/ActionBarSearchResultsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/ActionBarSearchResultsFingerprint.kt new file mode 100644 index 0000000000..aa25433438 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/ActionBarSearchResultsFingerprint.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.youtube.layout.buttons.navigation.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patches.youtube.layout.buttons.navigation.ResolvePivotBarFingerprintsPatch +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 = { ResolvePivotBarFingerprintsPatch.actionBarSearchResultsViewMicId } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/utils/InjectionUtils.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/utils/InjectionUtils.kt index f97305c12c..e333acb78a 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/utils/InjectionUtils.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/utils/InjectionUtils.kt @@ -15,7 +15,7 @@ internal object InjectionUtils { * @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) { + fun MutableMethod.injectHook(insertIndex: Int, hook: String) { val injectTarget = this // Register to pass to the hook 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 ad9f6b20d4..ff68576363 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,14 +12,17 @@ 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 import app.revanced.patches.shared.misc.settings.preference.TextPreference +import app.revanced.patches.youtube.layout.buttons.navigation.NavigationButtonsPatch import app.revanced.patches.youtube.layout.hide.general.fingerprints.ParseElementFromBufferFingerprint import app.revanced.patches.youtube.layout.hide.general.fingerprints.PlayerOverlayFingerprint import app.revanced.patches.youtube.layout.hide.general.fingerprints.ShowWatermarkFingerprint import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch +import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch import app.revanced.patches.youtube.misc.settings.SettingsPatch import app.revanced.util.exception import com.android.tools.smali.dexlib2.Opcode @@ -33,6 +36,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction LithoFilterPatch::class, SettingsPatch::class, AddResourcesPatch::class, + NavigationButtonsPatch::class, // FIXME: use a sub patch + PlayerTypeHookPatch::class // Used by Keyword Content filter. ], compatiblePackages = [ CompatiblePackage( @@ -121,12 +126,15 @@ object HideLayoutComponentsPatch : BytecodePatch( SettingsPatch.PreferenceScreen.FEED.addPreferences( PreferenceScreen( - key = "revanced_hide_keyword_content_preference_screen", + key = "revanced_hide_keyword_content_screen", sorting = Sorting.UNSORTED, preferences = setOf( - SwitchPreference("revanced_hide_keyword_content"), + SwitchPreference("revanced_hide_keyword_content_search"), + SwitchPreference("revanced_hide_keyword_content_home"), + SwitchPreference("revanced_hide_keyword_content_subscriptions"), TextPreference("revanced_hide_keyword_content_phrases", inputType = InputType.TEXT_MULTI_LINE), - ), + NonInteractivePreference("revanced_hide_keyword_content_about") + ) ) ) diff --git a/src/main/resources/addresources/values/strings.xml b/src/main/resources/addresources/values/strings.xml index 12db801a4d..f9b51073ff 100644 --- a/src/main/resources/addresources/values/strings.xml +++ b/src/main/resources/addresources/values/strings.xml @@ -168,13 +168,21 @@ Custom filter List of component path builder strings to filter separated by new line Invalid custom filter: %s - Hide keyword content - Hide feed and search result videos using keyword filters - Enable keyword filtering - Feed/search is filtered to hide content that matches keyword phrases\n\nLimitations\n• Some Shorts may not be hidden\n• Some UI elements may not be hidden\n• Searching for a keyword may show no results - Feed/search results are not filtered by keywords + Hide keyword content + Hide feed and search result 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 keywordsx + Videos in the subscriptions tab are filtered by keywords + Videos in the subscriptions tab are not filtered by keywords + Hide search results by keywordsx + 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 elements may not be hidden\n• Searching for a keyword may show no results Invalid keyword length (must be at least %s characters): %s From 1e2f8a10f2e7e91c7bd2ff54003a894bbcf16566 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 14 Mar 2024 18:13:25 +0400 Subject: [PATCH 12/26] refactor: break apart NavigationButtonsPatch into subpatch --- api/revanced-patches.api | 7 + .../navigation/NavigationButtonsPatch.kt | 105 ++---------- .../ResolvePivotBarFingerprintsPatch.kt | 42 ----- .../hide/general/HideLayoutComponentsPatch.kt | 4 +- .../misc/navigation/NavigationBarHookPatch.kt | 151 ++++++++++++++++++ .../NavigationBarHookResourcePatch.kt | 24 +++ .../ActionBarSearchResultsFingerprint.kt | 6 +- .../InitializeButtonsFingerprint.kt | 9 +- .../NavigationBarHookCallbackFingerprint.kt | 24 +++ .../PivotBarButtonsViewFingerprint.kt | 5 +- .../PivotBarConstructorFingerprint.kt | 2 +- .../PivotBarCreateButtonViewFingerprint.kt | 5 +- .../fingerprints/PivotBarEnumFingerprint.kt | 5 +- .../navigation/utils/InjectionUtils.kt | 2 +- 14 files changed, 241 insertions(+), 150 deletions(-) delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/ResolvePivotBarFingerprintsPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookResourcePatch.kt rename src/main/kotlin/app/revanced/patches/youtube/{layout/buttons => misc}/navigation/fingerprints/ActionBarSearchResultsFingerprint.kt (59%) rename src/main/kotlin/app/revanced/patches/youtube/{layout/buttons => misc}/navigation/fingerprints/InitializeButtonsFingerprint.kt (52%) create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/NavigationBarHookCallbackFingerprint.kt rename src/main/kotlin/app/revanced/patches/youtube/{layout/buttons => misc}/navigation/fingerprints/PivotBarButtonsViewFingerprint.kt (69%) rename src/main/kotlin/app/revanced/patches/youtube/{layout/buttons => misc}/navigation/fingerprints/PivotBarConstructorFingerprint.kt (82%) rename src/main/kotlin/app/revanced/patches/youtube/{layout/buttons => misc}/navigation/fingerprints/PivotBarCreateButtonViewFingerprint.kt (70%) rename src/main/kotlin/app/revanced/patches/youtube/{layout/buttons => misc}/navigation/fingerprints/PivotBarEnumFingerprint.kt (73%) rename src/main/kotlin/app/revanced/patches/youtube/{layout/buttons => misc}/navigation/utils/InjectionUtils.kt (94%) diff --git a/api/revanced-patches.api b/api/revanced-patches.api index 4e1ad810a5..60bfb80d2d 100644 --- a/api/revanced-patches.api +++ b/api/revanced-patches.api @@ -1575,6 +1575,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 hookNavigationButtonCreated (Ljava/lang/String;)V +} + 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 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 117aad8134..fd948d35fe 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 @@ -1,7 +1,6 @@ package app.revanced.patches.youtube.layout.buttons.navigation 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.patch.BytecodePatch @@ -11,27 +10,22 @@ 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 app.revanced.util.getReference -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 -import com.android.tools.smali.dexlib2.iface.reference.MethodReference -// TODO: break this patch apart so other patches can check what tab is active (without depending on this patch). @Patch( name = "Navigation buttons", description = "Adds options to hide and change navigation buttons (such as the Shorts button).", dependencies = [ IntegrationsPatch::class, SettingsPatch::class, - ResolvePivotBarFingerprintsPatch::class, AddResourcesPatch::class, + NavigationBarHookPatch::class ], compatiblePackages = [ CompatiblePackage( @@ -60,10 +54,10 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference ) @Suppress("unused") object NavigationButtonsPatch : BytecodePatch( - setOf(AddCreateButtonViewFingerprint, ActionBarSearchResultsFingerprint), + setOf(AddCreateButtonViewFingerprint), ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = - "Lapp/revanced/integrations/youtube/patches/NavigationButtonsPatch;" + "Lapp/revanced/integrations/youtube/patches/HideNavigationButtonsPatch;" override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) @@ -83,50 +77,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 = "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->setLastAppNavigationEnum(Ljava/lang/Enum;)V" - val buttonHook = "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->navigationTabLoaded(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(insertIndex, hook) - } - - /* - * Hide create or switch it with notifications buttons. + * Switch create button with notification. */ AddCreateButtonViewFingerprint.result?.let { @@ -136,7 +87,8 @@ object NavigationButtonsPatch : BytecodePatch( }!!.index val conditionalCheckIndex = stringIndex - 1 - val conditionRegister = getInstruction(conditionalCheckIndex).registerA + val conditionRegister = + getInstruction(conditionalCheckIndex).registerA addInstructions( conditionalCheckIndex, @@ -148,43 +100,6 @@ 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 - mutableMethod.injectHook( - insertIndex, - "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->createTabLoaded(Landroid/view/View;)V" - ) - } - - /** - * Search bar TextView - */ - - // 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.result?.mutableMethod?.apply { - val instructionIndex = implementation!!.instructions.indexOfFirst { - it.opcode == Opcode.INVOKE_VIRTUAL && - it.getReference()?.name == "setLayoutDirection" - } - val register = getInstruction(instructionIndex).registerC - addInstruction( - instructionIndex, - "invoke-static { v$register }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->searchBarResultsViewLoaded(Landroid/view/View;)V" - ) - } ?: ActionBarSearchResultsFingerprint.exception + 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 3a11960b50..0000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/ResolvePivotBarFingerprintsPatch.kt +++ /dev/null @@ -1,42 +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.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 - internal var actionBarSearchResultsViewMicId: Long = -1 - - override fun execute(context: BytecodeContext) { - // imageOnlyTabResourceId is used in InitializeButtonsFingerprint fingerprint - imageOnlyTabResourceId = ResourceMappingPatch.resourceMappings.single { - it.type == "layout" && it.name == "image_only_tab" - }.id - - actionBarSearchResultsViewMicId = ResourceMappingPatch.resourceMappings.single { - it.type == "layout" && it.name == "action_bar_search_results_view_mic" - }.id - - 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 - } - -} \ No newline at end of file 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 ff68576363..487c88ad92 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 @@ -17,7 +17,7 @@ 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.shared.misc.settings.preference.TextPreference -import app.revanced.patches.youtube.layout.buttons.navigation.NavigationButtonsPatch +import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch import app.revanced.patches.youtube.layout.hide.general.fingerprints.ParseElementFromBufferFingerprint import app.revanced.patches.youtube.layout.hide.general.fingerprints.PlayerOverlayFingerprint import app.revanced.patches.youtube.layout.hide.general.fingerprints.ShowWatermarkFingerprint @@ -36,7 +36,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction LithoFilterPatch::class, SettingsPatch::class, AddResourcesPatch::class, - NavigationButtonsPatch::class, // FIXME: use a sub patch + NavigationBarHookPatch::class, PlayerTypeHookPatch::class // Used by Keyword Content filter. ], compatiblePackages = [ 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 0000000000..0bce6d4ce8 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt @@ -0,0 +1,151 @@ +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.patch.BytecodePatch +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.ActionBarSearchResultsFingerprint +import app.revanced.patches.youtube.misc.navigation.fingerprints.InitializeButtonsFingerprint +import app.revanced.patches.youtube.misc.navigation.fingerprints.NavigationBarHookCallbackFingerprint +import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarButtonsViewFingerprint +import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarConstructorFingerprint +import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarCreateButtonViewFingerprint +import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarEnumFingerprint +import app.revanced.patches.youtube.misc.navigation.utils.InjectionUtils.REGISTER_TEMPLATE_REPLACEMENT +import app.revanced.patches.youtube.misc.navigation.utils.InjectionUtils.injectHook +import app.revanced.util.exception +import app.revanced.util.getReference +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference + +@Patch( + description = "Hook to get the current navigation bar tab that is active, and if the search bar is active.", + dependencies = [ + IntegrationsPatch::class, + NavigationBarHookResourcePatch::class + ] +) +@Suppress("unused") +object NavigationBarHookPatch : BytecodePatch( + setOf( + PivotBarConstructorFingerprint, + ActionBarSearchResultsFingerprint, + NavigationBarHookCallbackFingerprint + ) +) { + 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;" + + private lateinit var navigationTabCreatedCallbackMethod: MutableMethod + + override fun execute(context: BytecodeContext) { + PivotBarConstructorFingerprint.result?.let { + InitializeButtonsFingerprint.resolve( + context, + it.classDef + ) + } ?: throw PivotBarConstructorFingerprint.exception + + val initializeButtonsResult = InitializeButtonsFingerprint.result + ?: throw InitializeButtonsFingerprint.exception + + 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 = "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + + "$INTEGRATIONS_CLASS_DESCRIPTOR->setLastAppNavigationEnum(Ljava/lang/Enum;)V" + val buttonHook = "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + + "$INTEGRATIONS_CLASS_DESCRIPTOR->navigationTabLoaded(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(insertIndex, hook) + } + + InitializeButtonsFingerprint.result?.let { + if (!PivotBarCreateButtonViewFingerprint.resolve(context, it.mutableMethod, it.mutableClass)) { + throw PivotBarCreateButtonViewFingerprint.exception + } + } ?: throw InitializeButtonsFingerprint.exception + + /** + * Unique hook just for the Create tab button. + */ + PivotBarCreateButtonViewFingerprint.result?.apply { + val insertIndex = scanResult.patternScanResult!!.endIndex + mutableMethod.injectHook( + insertIndex, + "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + + "$INTEGRATIONS_CLASS_DESCRIPTOR->createTabLoaded(Landroid/view/View;)V" + ) + } ?: PivotBarCreateButtonViewFingerprint.exception + + + /** + * Callback for other patches. + */ + NavigationBarHookCallbackFingerprint.result?.apply { + navigationTabCreatedCallbackMethod = mutableMethod + } ?: NavigationBarHookCallbackFingerprint.exception + + + /** + * 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.result?.mutableMethod?.apply { + val instructionIndex = implementation!!.instructions.indexOfFirst { + it.opcode == Opcode.INVOKE_VIRTUAL && + it.getReference()?.name == "setLayoutDirection" + } + val register = getInstruction(instructionIndex).registerC + addInstruction( + instructionIndex, + "invoke-static { v$register }, " + + "$INTEGRATIONS_CLASS_DESCRIPTOR->searchBarResultsViewLoaded(Landroid/view/View;)V" + ) + } ?: ActionBarSearchResultsFingerprint.exception + } + + fun hookNavigationButtonCreated(classDescriptor: String) { + navigationTabCreatedCallbackMethod.addInstruction( + 0, + "invoke-static { p0, p1 }, " + + "$classDescriptor->navigationTabCreated(${INTEGRATIONS_NAVIGATION_BUTTON_DESCRIPTOR}Landroid/view/View;)V" + ) + } +} 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 0000000000..fc515fd359 --- /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.single { + it.type == "layout" && it.name == "image_only_tab" + }.id + + actionBarSearchResultsViewMicId = ResourceMappingPatch.resourceMappings.single { + 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/layout/buttons/navigation/fingerprints/ActionBarSearchResultsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/ActionBarSearchResultsFingerprint.kt similarity index 59% rename from src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/ActionBarSearchResultsFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/ActionBarSearchResultsFingerprint.kt index aa25433438..2ba8106f99 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/ActionBarSearchResultsFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/ActionBarSearchResultsFingerprint.kt @@ -1,7 +1,7 @@ -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 @@ -9,5 +9,5 @@ internal object ActionBarSearchResultsFingerprint : LiteralValueFingerprint( accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, returnType = "Landroid/view/View;", parameters = listOf("Landroid/view/LayoutInflater;"), - literalSupplier = { ResolvePivotBarFingerprintsPatch.actionBarSearchResultsViewMicId } + 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 52% 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 f64015c78a..f91d1b36f3 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 0000000000..6cc2f8aa3b --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/NavigationBarHookCallbackFingerprint.kt @@ -0,0 +1,24 @@ +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 + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarButtonsViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarButtonsViewFingerprint.kt similarity index 69% rename from src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarButtonsViewFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarButtonsViewFingerprint.kt index 7827a4f4f4..cb8328dff8 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarButtonsViewFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarButtonsViewFingerprint.kt @@ -1,8 +1,11 @@ -package app.revanced.patches.youtube.layout.buttons.navigation.fingerprints +package app.revanced.patches.youtube.misc.navigation.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import com.android.tools.smali.dexlib2.Opcode +/** + * Resolves to the method found in [InitializeButtonsFingerprint]. + */ internal object PivotBarButtonsViewFingerprint : MethodFingerprint( opcodes = listOf( Opcode.INVOKE_VIRTUAL_RANGE, 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 37674a2bfc..57bc63e4d5 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/layout/buttons/navigation/fingerprints/PivotBarCreateButtonViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarCreateButtonViewFingerprint.kt similarity index 70% rename from src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarCreateButtonViewFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarCreateButtonViewFingerprint.kt index a32ee0cb71..f438eea73e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarCreateButtonViewFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarCreateButtonViewFingerprint.kt @@ -1,8 +1,11 @@ -package app.revanced.patches.youtube.layout.buttons.navigation.fingerprints +package app.revanced.patches.youtube.misc.navigation.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import com.android.tools.smali.dexlib2.Opcode +/** + * Resolves to the method found in [InitializeButtonsFingerprint]. + */ internal object PivotBarCreateButtonViewFingerprint : MethodFingerprint( opcodes = listOf( Opcode.INVOKE_DIRECT_RANGE, diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarEnumFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarEnumFingerprint.kt similarity index 73% rename from src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarEnumFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarEnumFingerprint.kt index df40cc9eb8..864873aa70 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/fingerprints/PivotBarEnumFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarEnumFingerprint.kt @@ -1,8 +1,11 @@ -package app.revanced.patches.youtube.layout.buttons.navigation.fingerprints +package app.revanced.patches.youtube.misc.navigation.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import com.android.tools.smali.dexlib2.Opcode +/** + * Resolves to the method found in [InitializeButtonsFingerprint]. + */ internal object PivotBarEnumFingerprint : MethodFingerprint( opcodes = listOf( Opcode.INVOKE_STATIC, diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/utils/InjectionUtils.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt similarity index 94% rename from src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/utils/InjectionUtils.kt rename to src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt index e333acb78a..7df2a4ab1c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/utils/InjectionUtils.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.youtube.layout.buttons.navigation.utils +package app.revanced.patches.youtube.misc.navigation.utils import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction From 53684573be810c040a1cac35e5725b8fcc4bedd3 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sun, 17 Mar 2024 19:09:28 +0400 Subject: [PATCH 13/26] Adjust setting strings --- src/main/resources/addresources/values/strings.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/resources/addresources/values/strings.xml b/src/main/resources/addresources/values/strings.xml index f9b51073ff..0046ce95c4 100644 --- a/src/main/resources/addresources/values/strings.xml +++ b/src/main/resources/addresources/values/strings.xml @@ -169,21 +169,21 @@ List of component path builder strings to filter separated by new line Invalid custom filter: %s Hide keyword content - Hide feed and search result videos using keyword filters + Hide search and feed videos using keyword filters + Hide search results by keywordsx + Search results are filtered by keywords + Search results are not filtered by keywords 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 keywordsx Videos in the subscriptions tab are filtered by keywords Videos in the subscriptions tab are not filtered by keywords - Hide search results by keywordsx - 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 elements may not be hidden\n• Searching for a keyword may show no results - Invalid keyword length (must be at least %s characters): %s + Search/Home/Subscription 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 (must be at least %s characters): %s Hide general ads From 83545b4b9d434c5375d5c7b0a9e4d5068dda4e7e Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sun, 17 Mar 2024 19:16:07 +0400 Subject: [PATCH 14/26] refactor: Use existing class name --- .../youtube/layout/buttons/navigation/NavigationButtonsPatch.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 fd948d35fe..6d8844b7ba 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 @@ -57,7 +57,7 @@ object NavigationButtonsPatch : BytecodePatch( setOf(AddCreateButtonViewFingerprint), ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = - "Lapp/revanced/integrations/youtube/patches/HideNavigationButtonsPatch;" + "Lapp/revanced/integrations/youtube/patches/NavigationButtonsPatch;" override fun execute(context: BytecodeContext) { AddResourcesPatch(this::class) From 75220accf25fb6750a8636b96be0603bbcae625e Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sun, 17 Mar 2024 19:39:17 +0400 Subject: [PATCH 15/26] refactor: Simplify --- .../hide/general/HideLayoutComponentsPatch.kt | 19 ++++---- .../misc/navigation/NavigationBarHookPatch.kt | 44 ++++++++----------- .../NavigationBarHookResourcePatch.kt | 4 +- 3 files changed, 30 insertions(+), 37 deletions(-) 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 487c88ad92..f272111763 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 @@ -17,14 +17,14 @@ 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.shared.misc.settings.preference.TextPreference -import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch import app.revanced.patches.youtube.layout.hide.general.fingerprints.ParseElementFromBufferFingerprint import app.revanced.patches.youtube.layout.hide.general.fingerprints.PlayerOverlayFingerprint import app.revanced.patches.youtube.layout.hide.general.fingerprints.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 @@ -162,15 +162,14 @@ object HideLayoutComponentsPatch : BytecodePatch( // 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, @@ -182,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) @@ -201,7 +200,7 @@ object HideLayoutComponentsPatch : BytecodePatch( move-result p2 """, ) - } ?: throw ShowWatermarkFingerprint.exception + } // endregion } 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 index 0bce6d4ce8..3d4f917b27 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt @@ -16,8 +16,8 @@ import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarCreateB import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarEnumFingerprint import app.revanced.patches.youtube.misc.navigation.utils.InjectionUtils.REGISTER_TEMPLATE_REPLACEMENT import app.revanced.patches.youtube.misc.navigation.utils.InjectionUtils.injectHook -import app.revanced.util.exception import app.revanced.util.getReference +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.reference.MethodReference @@ -46,29 +46,25 @@ object NavigationBarHookPatch : BytecodePatch( private lateinit var navigationTabCreatedCallbackMethod: MutableMethod override fun execute(context: BytecodeContext) { - PivotBarConstructorFingerprint.result?.let { + PivotBarConstructorFingerprint.resultOrThrow().let { InitializeButtonsFingerprint.resolve( context, it.classDef ) - } ?: throw PivotBarConstructorFingerprint.exception + } - val initializeButtonsResult = InitializeButtonsFingerprint.result - ?: throw InitializeButtonsFingerprint.exception + val initializeButtonsResult = InitializeButtonsFingerprint.resultOrThrow() val fingerprintResults = arrayOf(PivotBarEnumFingerprint, PivotBarButtonsViewFingerprint) .onEach { - if (!it.resolve( - context, - initializeButtonsResult.mutableMethod, - initializeButtonsResult.mutableClass, - ) - ) { - throw it.exception - } + it.resolve( + context, + initializeButtonsResult.mutableMethod, + initializeButtonsResult.mutableClass, + ) } - .map { it.result!!.scanResult.patternScanResult!! } + .map { it.resultOrThrow().scanResult.patternScanResult!! } val enumScanResult = fingerprintResults[0] val buttonViewResult = fingerprintResults[1] @@ -93,31 +89,29 @@ object NavigationBarHookPatch : BytecodePatch( initializeButtonsResult.mutableMethod.injectHook(insertIndex, hook) } - InitializeButtonsFingerprint.result?.let { - if (!PivotBarCreateButtonViewFingerprint.resolve(context, it.mutableMethod, it.mutableClass)) { - throw PivotBarCreateButtonViewFingerprint.exception - } - } ?: throw InitializeButtonsFingerprint.exception + InitializeButtonsFingerprint.resultOrThrow().let { + PivotBarCreateButtonViewFingerprint.resolve(context, it.mutableMethod, it.mutableClass) + } /** * Unique hook just for the Create tab button. */ - PivotBarCreateButtonViewFingerprint.result?.apply { + PivotBarCreateButtonViewFingerprint.resultOrThrow().apply { val insertIndex = scanResult.patternScanResult!!.endIndex mutableMethod.injectHook( insertIndex, "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + "$INTEGRATIONS_CLASS_DESCRIPTOR->createTabLoaded(Landroid/view/View;)V" ) - } ?: PivotBarCreateButtonViewFingerprint.exception + } /** * Callback for other patches. */ - NavigationBarHookCallbackFingerprint.result?.apply { + NavigationBarHookCallbackFingerprint.resultOrThrow().apply { navigationTabCreatedCallbackMethod = mutableMethod - } ?: NavigationBarHookCallbackFingerprint.exception + } /** @@ -127,7 +121,7 @@ object NavigationBarHookPatch : BytecodePatch( // 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.result?.mutableMethod?.apply { + ActionBarSearchResultsFingerprint.resultOrThrow().mutableMethod.apply { val instructionIndex = implementation!!.instructions.indexOfFirst { it.opcode == Opcode.INVOKE_VIRTUAL && it.getReference()?.name == "setLayoutDirection" @@ -138,7 +132,7 @@ object NavigationBarHookPatch : BytecodePatch( "invoke-static { v$register }, " + "$INTEGRATIONS_CLASS_DESCRIPTOR->searchBarResultsViewLoaded(Landroid/view/View;)V" ) - } ?: ActionBarSearchResultsFingerprint.exception + } } fun hookNavigationButtonCreated(classDescriptor: String) { 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 index fc515fd359..3841f2bfaa 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookResourcePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookResourcePatch.kt @@ -13,11 +13,11 @@ internal object NavigationBarHookResourcePatch : ResourcePatch() { internal var actionBarSearchResultsViewMicId: Long = -1 override fun execute(context: ResourceContext) { - imageOnlyTabResourceId = ResourceMappingPatch.resourceMappings.single { + imageOnlyTabResourceId = ResourceMappingPatch.resourceMappings.first { it.type == "layout" && it.name == "image_only_tab" }.id - actionBarSearchResultsViewMicId = ResourceMappingPatch.resourceMappings.single { + actionBarSearchResultsViewMicId = ResourceMappingPatch.resourceMappings.first { it.type == "layout" && it.name == "action_bar_search_results_view_mic" }.id } From 05c03f3a583fe429082a06240976cfa5cb756d27 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Tue, 19 Mar 2024 11:03:01 +0400 Subject: [PATCH 16/26] refactor: Cleanup --- .../youtube/misc/navigation/NavigationBarHookPatch.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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 index 3d4f917b27..aab31e4f6f 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt @@ -89,13 +89,16 @@ object NavigationBarHookPatch : BytecodePatch( initializeButtonsResult.mutableMethod.injectHook(insertIndex, hook) } - InitializeButtonsFingerprint.resultOrThrow().let { - PivotBarCreateButtonViewFingerprint.resolve(context, it.mutableMethod, it.mutableClass) - } /** * Unique hook just for the Create tab button. */ + PivotBarCreateButtonViewFingerprint.resolve( + context, + initializeButtonsResult.mutableMethod, + initializeButtonsResult.mutableClass + ) + PivotBarCreateButtonViewFingerprint.resultOrThrow().apply { val insertIndex = scanResult.patternScanResult!!.endIndex mutableMethod.injectHook( From b8aa8eacb084b53f0427456054b6d841325a5064 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Tue, 19 Mar 2024 20:03:24 +0400 Subject: [PATCH 17/26] fix: Detect some keywords that will always hide all videos --- src/main/resources/addresources/values/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/addresources/values/strings.xml b/src/main/resources/addresources/values/strings.xml index 0046ce95c4..e4e786cf0a 100644 --- a/src/main/resources/addresources/values/strings.xml +++ b/src/main/resources/addresources/values/strings.xml @@ -183,6 +183,7 @@ 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 Search/Home/Subscription 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 (must be at least %s characters): %s From 2094b9df18f300eddc7b3b809d8bfa1dd89f9fb4 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 21 Mar 2024 12:10:32 +0400 Subject: [PATCH 18/26] fix: Adjust settings text --- .../layout/hide/general/HideLayoutComponentsPatch.kt | 2 +- src/main/resources/addresources/values/strings.xml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) 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 f272111763..9e5e8cfb6d 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 @@ -129,9 +129,9 @@ object HideLayoutComponentsPatch : BytecodePatch( key = "revanced_hide_keyword_content_screen", sorting = Sorting.UNSORTED, preferences = setOf( - SwitchPreference("revanced_hide_keyword_content_search"), 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") ) diff --git a/src/main/resources/addresources/values/strings.xml b/src/main/resources/addresources/values/strings.xml index e4e786cf0a..de5435df50 100644 --- a/src/main/resources/addresources/values/strings.xml +++ b/src/main/resources/addresources/values/strings.xml @@ -170,21 +170,21 @@ Invalid custom filter: %s Hide keyword content Hide search and feed videos using keyword filters - Hide search results by keywordsx - Search results are filtered by keywords - Search results are not filtered by keywords 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 keywordsx Videos in the subscriptions tab are filtered by keywords Videos in the subscriptions tab are not filtered by keywords + Hide search results by keywordsx + 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 - Search/Home/Subscription 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 + 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 (must be at least %s characters): %s + Invalid keyword. \'%s\' is less than %s characters Hide general ads From 0de51bf9659b94075ab1c09b6a0d219158eb3c8a Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 21 Mar 2024 15:56:10 +0400 Subject: [PATCH 19/26] fix: Hook the 'You' library tab --- .../misc/navigation/NavigationBarHookPatch.kt | 103 ++++++++---------- .../YouNavigationTabFingerprint.kt | 16 +++ .../misc/navigation/utils/InjectionUtils.kt | 11 +- .../resources/addresources/values/strings.xml | 2 +- 4 files changed, 66 insertions(+), 66 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/YouNavigationTabFingerprint.kt 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 index aab31e4f6f..ab90c6d48f 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt @@ -3,6 +3,7 @@ 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.fingerprint.MethodFingerprint import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod @@ -14,6 +15,7 @@ import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarButtons import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarConstructorFingerprint import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarCreateButtonViewFingerprint import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarEnumFingerprint +import app.revanced.patches.youtube.misc.navigation.fingerprints.YouNavigationTabFingerprint import app.revanced.patches.youtube.misc.navigation.utils.InjectionUtils.REGISTER_TEMPLATE_REPLACEMENT import app.revanced.patches.youtube.misc.navigation.utils.InjectionUtils.injectHook import app.revanced.util.getReference @@ -33,8 +35,8 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference object NavigationBarHookPatch : BytecodePatch( setOf( PivotBarConstructorFingerprint, - ActionBarSearchResultsFingerprint, - NavigationBarHookCallbackFingerprint + NavigationBarHookCallbackFingerprint, + ActionBarSearchResultsFingerprint ) ) { internal const val INTEGRATIONS_CLASS_DESCRIPTOR = @@ -46,69 +48,55 @@ object NavigationBarHookPatch : BytecodePatch( private lateinit var navigationTabCreatedCallbackMethod: MutableMethod override fun execute(context: BytecodeContext) { - PivotBarConstructorFingerprint.resultOrThrow().let { - InitializeButtonsFingerprint.resolve( - context, - it.classDef - ) - } - - val initializeButtonsResult = InitializeButtonsFingerprint.resultOrThrow() - - val fingerprintResults = - arrayOf(PivotBarEnumFingerprint, PivotBarButtonsViewFingerprint) - .onEach { - it.resolve( - context, - initializeButtonsResult.mutableMethod, - initializeButtonsResult.mutableClass, - ) - } - .map { it.resultOrThrow().scanResult.patternScanResult!! } - - val enumScanResult = fingerprintResults[0] - val buttonViewResult = fingerprintResults[1] - - val enumHookInsertIndex = enumScanResult.startIndex + 2 - val buttonHookInsertIndex = buttonViewResult.endIndex + InitializeButtonsFingerprint.resolve( + context, + PivotBarConstructorFingerprint.resultOrThrow().classDef + ) - /* - * Inject hooks - */ + fun MethodFingerprint.patternScanResult() = resultOrThrow().scanResult.patternScanResult!! - val enumHook = "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->setLastAppNavigationEnum(Ljava/lang/Enum;)V" - val buttonHook = "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->navigationTabLoaded(Landroid/view/View;)V" + // All of these hooks can be found by filtering the method for the calls to PivotBar + // and calls to lookup the Navigation enum. + // But the 'You' tab does not have an enum and that approach makes this patch a bit more complicated. + InitializeButtonsFingerprint.resultOrThrow().apply { - // Inject bottom to top to not mess up the indices - mapOf( - buttonHook to buttonHookInsertIndex, - enumHook to enumHookInsertIndex, - ).forEach { (hook, insertIndex) -> - initializeButtonsResult.mutableMethod.injectHook(insertIndex, hook) - } + PivotBarEnumFingerprint.also { + it.resolve(context, mutableMethod, mutableClass) + mutableMethod.injectHook( + it.patternScanResult().startIndex + 2, + "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + + "$INTEGRATIONS_CLASS_DESCRIPTOR->setLastAppNavigationEnum(Ljava/lang/Enum;)V" + ) + } + PivotBarButtonsViewFingerprint.also { + it.resolve(context, mutableMethod, mutableClass) + mutableMethod.injectHook( + it.patternScanResult().endIndex, + "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + + "$INTEGRATIONS_CLASS_DESCRIPTOR->navigationTabLoaded(Landroid/view/View;)V" + ) + } - /** - * Unique hook just for the Create tab button. - */ - PivotBarCreateButtonViewFingerprint.resolve( - context, - initializeButtonsResult.mutableMethod, - initializeButtonsResult.mutableClass - ) + YouNavigationTabFingerprint.also { + it.resolve(context, mutableMethod, mutableClass) + mutableMethod.injectHook( + it.patternScanResult().startIndex + 3, + "invoke-static/range { v$REGISTER_TEMPLATE_REPLACEMENT .. v$REGISTER_TEMPLATE_REPLACEMENT }, " + + "$INTEGRATIONS_CLASS_DESCRIPTOR->youTabLoaded(Landroid/view/View;)V" + ) + } - PivotBarCreateButtonViewFingerprint.resultOrThrow().apply { - val insertIndex = scanResult.patternScanResult!!.endIndex - mutableMethod.injectHook( - insertIndex, - "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->createTabLoaded(Landroid/view/View;)V" - ) + PivotBarCreateButtonViewFingerprint.also { + it.resolve(context, mutableMethod, mutableClass) + mutableMethod.injectHook( + it.patternScanResult().endIndex, + "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + + "$INTEGRATIONS_CLASS_DESCRIPTOR->createTabLoaded(Landroid/view/View;)V" + ) + } } - /** * Callback for other patches. */ @@ -116,7 +104,6 @@ object NavigationBarHookPatch : BytecodePatch( navigationTabCreatedCallbackMethod = mutableMethod } - /** * Search bar. */ diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/YouNavigationTabFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/YouNavigationTabFingerprint.kt new file mode 100644 index 0000000000..0ceab8e9dc --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/YouNavigationTabFingerprint.kt @@ -0,0 +1,16 @@ +package app.revanced.patches.youtube.misc.navigation.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.Opcode + +/** + * Resolves to the method found in [InitializeButtonsFingerprint]. + */ +internal object YouNavigationTabFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.INVOKE_DIRECT_RANGE, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, // target reference + Opcode.GOTO_16 + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt index 7df2a4ab1c..92ff564c8d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt @@ -3,7 +3,6 @@ package app.revanced.patches.youtube.misc.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 { @@ -13,18 +12,16 @@ internal object InjectionUtils { * 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]. + * a [OneRegisterInstruction] must be present before [insertIndex]. */ fun MutableMethod.injectHook(insertIndex: Int, hook: String) { - 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 + val register = getInstruction(registerIndex).registerA - injectTarget.addInstruction( + addInstruction( insertIndex, - hook.replace("REGISTER_INDEX", register.toString()), + hook.replace("REGISTER_INDEX", register.toString()) ) } } \ No newline at end of file diff --git a/src/main/resources/addresources/values/strings.xml b/src/main/resources/addresources/values/strings.xml index de5435df50..d3eb75b29c 100644 --- a/src/main/resources/addresources/values/strings.xml +++ b/src/main/resources/addresources/values/strings.xml @@ -176,7 +176,7 @@ Hide subscription videos by keywordsx Videos in the subscriptions tab are filtered by keywords Videos in the subscriptions tab are not filtered by keywords - Hide search results by keywordsx + Hide search results by keywords Search results are filtered by keywords Search results are not filtered by keywords Keywords to hide From 1db7ddb20fc27efb85e5030f5efee6f4379ce67f Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sun, 24 Mar 2024 19:27:33 +0400 Subject: [PATCH 20/26] refactor: No fingerprint opcodes. Changes needed for future YT 19.10 support. --- .../misc/navigation/NavigationBarHookPatch.kt | 83 +++++++++---------- .../fingerprints/NavigationEnumFingerprint.kt | 21 +++++ ...BarButtonsCreateDrawableViewFingerprint.kt | 17 ++++ ...BarButtonsCreateResourceViewFingerprint.kt | 14 ++++ .../PivotBarButtonsViewFingerprint.kt | 15 ---- .../PivotBarCreateButtonViewFingerprint.kt | 16 ---- .../fingerprints/PivotBarEnumFingerprint.kt | 18 ---- .../YouNavigationTabFingerprint.kt | 16 ---- .../misc/navigation/utils/InjectionUtils.kt | 23 +++++ 9 files changed, 114 insertions(+), 109 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/NavigationEnumFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarButtonsCreateDrawableViewFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarButtonsCreateResourceViewFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarButtonsViewFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarCreateButtonViewFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarEnumFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/YouNavigationTabFingerprint.kt 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 index ab90c6d48f..bfe1d8fb6c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt @@ -3,7 +3,6 @@ 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.fingerprint.MethodFingerprint import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod @@ -11,13 +10,12 @@ import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.navigation.fingerprints.ActionBarSearchResultsFingerprint import app.revanced.patches.youtube.misc.navigation.fingerprints.InitializeButtonsFingerprint import app.revanced.patches.youtube.misc.navigation.fingerprints.NavigationBarHookCallbackFingerprint -import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarButtonsViewFingerprint +import app.revanced.patches.youtube.misc.navigation.fingerprints.NavigationEnumFingerprint +import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarButtonsCreateDrawableViewFingerprint +import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarButtonsCreateResourceViewFingerprint import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarConstructorFingerprint -import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarCreateButtonViewFingerprint -import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarEnumFingerprint -import app.revanced.patches.youtube.misc.navigation.fingerprints.YouNavigationTabFingerprint import app.revanced.patches.youtube.misc.navigation.utils.InjectionUtils.REGISTER_TEMPLATE_REPLACEMENT -import app.revanced.patches.youtube.misc.navigation.utils.InjectionUtils.injectHook +import app.revanced.patches.youtube.misc.navigation.utils.InjectionUtils.injectHooksByFilter import app.revanced.util.getReference import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -35,6 +33,9 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference object NavigationBarHookPatch : BytecodePatch( setOf( PivotBarConstructorFingerprint, + NavigationEnumFingerprint, + PivotBarButtonsCreateDrawableViewFingerprint, + PivotBarButtonsCreateResourceViewFingerprint, NavigationBarHookCallbackFingerprint, ActionBarSearchResultsFingerprint ) @@ -53,48 +54,42 @@ object NavigationBarHookPatch : BytecodePatch( PivotBarConstructorFingerprint.resultOrThrow().classDef ) - fun MethodFingerprint.patternScanResult() = resultOrThrow().scanResult.patternScanResult!! - - // All of these hooks can be found by filtering the method for the calls to PivotBar - // and calls to lookup the Navigation enum. - // But the 'You' tab does not have an enum and that approach makes this patch a bit more complicated. InitializeButtonsFingerprint.resultOrThrow().apply { - PivotBarEnumFingerprint.also { - it.resolve(context, mutableMethod, mutableClass) - mutableMethod.injectHook( - it.patternScanResult().startIndex + 2, - "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->setLastAppNavigationEnum(Ljava/lang/Enum;)V" - ) - } - - PivotBarButtonsViewFingerprint.also { - it.resolve(context, mutableMethod, mutableClass) - mutableMethod.injectHook( - it.patternScanResult().endIndex, - "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->navigationTabLoaded(Landroid/view/View;)V" - ) - } + // Hook the navigation enum. Note: The 'You' tab does not have an enum hook. + val navigationEnumClassName = NavigationEnumFingerprint.resultOrThrow().mutableClass.type + mutableMethod.injectHooksByFilter( + { + it.opcode == Opcode.INVOKE_STATIC && + it.getReference()?.definingClass == navigationEnumClassName + }, + "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + + "$INTEGRATIONS_CLASS_DESCRIPTOR->setLastAppNavigationEnum(Ljava/lang/Enum;)V" + ) - YouNavigationTabFingerprint.also { - it.resolve(context, mutableMethod, mutableClass) - mutableMethod.injectHook( - it.patternScanResult().startIndex + 3, - "invoke-static/range { v$REGISTER_TEMPLATE_REPLACEMENT .. v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->youTabLoaded(Landroid/view/View;)V" - ) - } + // Hook the creation of navigation tab views. + val drawableTabResult = PivotBarButtonsCreateDrawableViewFingerprint.resultOrThrow() + mutableMethod.injectHooksByFilter( + { + // Don't need to check for the opcode since the method reference already validates. + val reference = it.getReference() + reference?.definingClass == drawableTabResult.mutableClass.type && + reference.name == drawableTabResult.mutableMethod.name + }, + "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + + "$INTEGRATIONS_CLASS_DESCRIPTOR->navigationTabLoaded(Landroid/view/View;)V" + ) - PivotBarCreateButtonViewFingerprint.also { - it.resolve(context, mutableMethod, mutableClass) - mutableMethod.injectHook( - it.patternScanResult().endIndex, - "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->createTabLoaded(Landroid/view/View;)V" - ) - } + val imageResourceTabResult = PivotBarButtonsCreateResourceViewFingerprint.resultOrThrow() + mutableMethod.injectHooksByFilter( + { + val reference = it.getReference() + reference?.definingClass == imageResourceTabResult.mutableClass.type && + reference.name == imageResourceTabResult.mutableMethod.name + }, + "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + + "$INTEGRATIONS_CLASS_DESCRIPTOR->navigationImageResourceTabLoaded(Landroid/view/View;)V" + ) } /** 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 0000000000..c084cf5ec1 --- /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 0000000000..0192f6e3d4 --- /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 0000000000..cef0b517eb --- /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/misc/navigation/fingerprints/PivotBarButtonsViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarButtonsViewFingerprint.kt deleted file mode 100644 index cb8328dff8..0000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarButtonsViewFingerprint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package app.revanced.patches.youtube.misc.navigation.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.Opcode - -/** - * Resolves to the method found in [InitializeButtonsFingerprint]. - */ -internal object PivotBarButtonsViewFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.INVOKE_VIRTUAL_RANGE, - Opcode.MOVE_RESULT_OBJECT, // target reference - Opcode.GOTO, - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarCreateButtonViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarCreateButtonViewFingerprint.kt deleted file mode 100644 index f438eea73e..0000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarCreateButtonViewFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.youtube.misc.navigation.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.Opcode - -/** - * Resolves to the method found in [InitializeButtonsFingerprint]. - */ -internal object PivotBarCreateButtonViewFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.INVOKE_DIRECT_RANGE, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarEnumFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarEnumFingerprint.kt deleted file mode 100644 index 864873aa70..0000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/PivotBarEnumFingerprint.kt +++ /dev/null @@ -1,18 +0,0 @@ -package app.revanced.patches.youtube.misc.navigation.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.Opcode - -/** - * Resolves to the method found in [InitializeButtonsFingerprint]. - */ -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, - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/YouNavigationTabFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/YouNavigationTabFingerprint.kt deleted file mode 100644 index 0ceab8e9dc..0000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/YouNavigationTabFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.youtube.misc.navigation.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.Opcode - -/** - * Resolves to the method found in [InitializeButtonsFingerprint]. - */ -internal object YouNavigationTabFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.INVOKE_DIRECT_RANGE, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, // target reference - Opcode.GOTO_16 - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt index 92ff564c8d..dddd02b5bf 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt @@ -2,7 +2,9 @@ package app.revanced.patches.youtube.misc.navigation.utils import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.patch.PatchException import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod +import com.android.tools.smali.dexlib2.builder.BuilderInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction internal object InjectionUtils { @@ -24,4 +26,25 @@ internal object InjectionUtils { hook.replace("REGISTER_INDEX", register.toString()) ) } + + /** + * @param insertionFilter Filter that identifies method calls with a non void return type. + */ + fun MutableMethod.injectHooksByFilter( + insertionFilter: (BuilderInstruction) -> Boolean, + hook: String + ) { + val methodInstructions = implementation!!.instructions + methodInstructions.filter(insertionFilter).let { filteredInstructions -> + if (filteredInstructions.isEmpty()) throw PatchException("Could not find insertion indexes") + filteredInstructions.forEach { + val index = methodInstructions.indexOf(it) + val register = (getInstruction(index + 1) as OneRegisterInstruction).registerA + addInstruction( + index + 2, + hook.replace("REGISTER_INDEX", register.toString()), + ) + } + } + } } \ No newline at end of file From 001d210a7071d697017484833136649911aca69c Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Tue, 26 Mar 2024 19:22:06 +0100 Subject: [PATCH 21/26] adjust description --- .../misc/navigation/NavigationBarHookPatch.kt | 39 ++++++++----------- 1 file changed, 16 insertions(+), 23 deletions(-) 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 index bfe1d8fb6c..684662df67 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt @@ -7,13 +7,7 @@ import app.revanced.patcher.patch.BytecodePatch 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.ActionBarSearchResultsFingerprint -import app.revanced.patches.youtube.misc.navigation.fingerprints.InitializeButtonsFingerprint -import app.revanced.patches.youtube.misc.navigation.fingerprints.NavigationBarHookCallbackFingerprint -import app.revanced.patches.youtube.misc.navigation.fingerprints.NavigationEnumFingerprint -import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarButtonsCreateDrawableViewFingerprint -import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarButtonsCreateResourceViewFingerprint -import app.revanced.patches.youtube.misc.navigation.fingerprints.PivotBarConstructorFingerprint +import app.revanced.patches.youtube.misc.navigation.fingerprints.* import app.revanced.patches.youtube.misc.navigation.utils.InjectionUtils.REGISTER_TEMPLATE_REPLACEMENT import app.revanced.patches.youtube.misc.navigation.utils.InjectionUtils.injectHooksByFilter import app.revanced.util.getReference @@ -23,11 +17,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Patch( - description = "Hook to get the current navigation bar tab that is active, and if the search bar is active.", + description = "Hooks the active navigation or search bar.", dependencies = [ IntegrationsPatch::class, - NavigationBarHookResourcePatch::class - ] + NavigationBarHookResourcePatch::class, + ], ) @Suppress("unused") object NavigationBarHookPatch : BytecodePatch( @@ -37,8 +31,8 @@ object NavigationBarHookPatch : BytecodePatch( PivotBarButtonsCreateDrawableViewFingerprint, PivotBarButtonsCreateResourceViewFingerprint, NavigationBarHookCallbackFingerprint, - ActionBarSearchResultsFingerprint - ) + ActionBarSearchResultsFingerprint, + ), ) { internal const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/shared/NavigationBar;" @@ -51,20 +45,19 @@ object NavigationBarHookPatch : BytecodePatch( override fun execute(context: BytecodeContext) { InitializeButtonsFingerprint.resolve( context, - PivotBarConstructorFingerprint.resultOrThrow().classDef + PivotBarConstructorFingerprint.resultOrThrow().classDef, ) InitializeButtonsFingerprint.resultOrThrow().apply { - // Hook the navigation enum. Note: The 'You' tab does not have an enum hook. val navigationEnumClassName = NavigationEnumFingerprint.resultOrThrow().mutableClass.type mutableMethod.injectHooksByFilter( { it.opcode == Opcode.INVOKE_STATIC && - it.getReference()?.definingClass == navigationEnumClassName + it.getReference()?.definingClass == navigationEnumClassName }, "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->setLastAppNavigationEnum(Ljava/lang/Enum;)V" + "$INTEGRATIONS_CLASS_DESCRIPTOR->setLastAppNavigationEnum(Ljava/lang/Enum;)V", ) // Hook the creation of navigation tab views. @@ -74,10 +67,10 @@ object NavigationBarHookPatch : BytecodePatch( // Don't need to check for the opcode since the method reference already validates. val reference = it.getReference() reference?.definingClass == drawableTabResult.mutableClass.type && - reference.name == drawableTabResult.mutableMethod.name + reference.name == drawableTabResult.mutableMethod.name }, "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->navigationTabLoaded(Landroid/view/View;)V" + "$INTEGRATIONS_CLASS_DESCRIPTOR->navigationTabLoaded(Landroid/view/View;)V", ) val imageResourceTabResult = PivotBarButtonsCreateResourceViewFingerprint.resultOrThrow() @@ -85,10 +78,10 @@ object NavigationBarHookPatch : BytecodePatch( { val reference = it.getReference() reference?.definingClass == imageResourceTabResult.mutableClass.type && - reference.name == imageResourceTabResult.mutableMethod.name + reference.name == imageResourceTabResult.mutableMethod.name }, "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->navigationImageResourceTabLoaded(Landroid/view/View;)V" + "$INTEGRATIONS_CLASS_DESCRIPTOR->navigationImageResourceTabLoaded(Landroid/view/View;)V", ) } @@ -109,13 +102,13 @@ object NavigationBarHookPatch : BytecodePatch( ActionBarSearchResultsFingerprint.resultOrThrow().mutableMethod.apply { val instructionIndex = implementation!!.instructions.indexOfFirst { it.opcode == Opcode.INVOKE_VIRTUAL && - it.getReference()?.name == "setLayoutDirection" + it.getReference()?.name == "setLayoutDirection" } val register = getInstruction(instructionIndex).registerC addInstruction( instructionIndex, "invoke-static { v$register }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->searchBarResultsViewLoaded(Landroid/view/View;)V" + "$INTEGRATIONS_CLASS_DESCRIPTOR->searchBarResultsViewLoaded(Landroid/view/View;)V", ) } } @@ -124,7 +117,7 @@ object NavigationBarHookPatch : BytecodePatch( navigationTabCreatedCallbackMethod.addInstruction( 0, "invoke-static { p0, p1 }, " + - "$classDescriptor->navigationTabCreated(${INTEGRATIONS_NAVIGATION_BUTTON_DESCRIPTOR}Landroid/view/View;)V" + "$classDescriptor->navigationTabCreated(${INTEGRATIONS_NAVIGATION_BUTTON_DESCRIPTOR}Landroid/view/View;)V", ) } } From c7d18e27d857e378f1cd6095e052f3f004d4b101 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Tue, 26 Mar 2024 20:01:07 +0100 Subject: [PATCH 22/26] refactor --- api/revanced-patches.api | 2 +- .../navigation/NavigationButtonsPatch.kt | 10 +- .../misc/navigation/NavigationBarHookPatch.kt | 121 +++++++++--------- .../NavigationBarHookCallbackFingerprint.kt | 13 +- .../misc/navigation/utils/InjectionUtils.kt | 7 +- 5 files changed, 74 insertions(+), 79 deletions(-) diff --git a/api/revanced-patches.api b/api/revanced-patches.api index 7de20cba64..521de80996 100644 --- a/api/revanced-patches.api +++ b/api/revanced-patches.api @@ -1613,7 +1613,7 @@ public final class app/revanced/patches/youtube/misc/navigation/NavigationBarHoo 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 hookNavigationButtonCreated (Ljava/lang/String;)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 { 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 6d8844b7ba..c660344deb 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 @@ -25,7 +25,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction IntegrationsPatch::class, SettingsPatch::class, AddResourcesPatch::class, - NavigationBarHookPatch::class + NavigationBarHookPatch::class, ], compatiblePackages = [ CompatiblePackage( @@ -47,7 +47,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction "19.06.39", "19.07.40", "19.08.36", - "19.09.37" + "19.09.37", ], ), ], @@ -76,10 +76,7 @@ object NavigationButtonsPatch : BytecodePatch( ), ) - /* - * Switch create button with notification. - */ - + // Switch create with notifications button. AddCreateButtonViewFingerprint.result?.let { it.mutableMethod.apply { val stringIndex = it.scanResult.stringsScanResult!!.matches.find { match -> @@ -100,6 +97,7 @@ object NavigationButtonsPatch : BytecodePatch( } } ?: throw AddCreateButtonViewFingerprint.exception + // Hook navigation button created, in order to hide them. NavigationBarHookPatch.hookNavigationButtonCreated(INTEGRATIONS_CLASS_DESCRIPTOR) } } 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 index 684662df67..19c7a8dadf 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt @@ -3,18 +3,21 @@ 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.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.patches.youtube.misc.navigation.utils.InjectionUtils.REGISTER_TEMPLATE_REPLACEMENT -import app.revanced.patches.youtube.misc.navigation.utils.InjectionUtils.injectHooksByFilter 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.", @@ -40,84 +43,82 @@ object NavigationBarHookPatch : BytecodePatch( internal const val INTEGRATIONS_NAVIGATION_BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/youtube/shared/NavigationBar\$NavigationButton;" - private lateinit var navigationTabCreatedCallbackMethod: MutableMethod - override fun execute(context: BytecodeContext) { - InitializeButtonsFingerprint.resolve( - context, - PivotBarConstructorFingerprint.resultOrThrow().classDef, - ) + fun MutableMethod.addHook(hook: Hook, insertPredicate: Instruction.() -> Boolean) = + getInstructions().filter(insertPredicate).forEach { + val register = (getInstruction(it.location.index + 1) as OneRegisterInstruction).registerA + + addInstruction( + it.location.index + 2, + "invoke-static { v$register }, " + + "$INTEGRATIONS_CLASS_DESCRIPTOR->${hook.methodName}(${hook.parameters})V", + ) + } - InitializeButtonsFingerprint.resultOrThrow().apply { - // Hook the navigation enum. Note: The 'You' tab does not have an enum hook. + InitializeButtonsFingerprint.resolve(context, PivotBarConstructorFingerprint.resultOrThrow().classDef) + InitializeButtonsFingerprint.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 - mutableMethod.injectHooksByFilter( - { - it.opcode == Opcode.INVOKE_STATIC && - it.getReference()?.definingClass == navigationEnumClassName - }, - "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->setLastAppNavigationEnum(Ljava/lang/Enum;)V", - ) + addHook(Hook.SET_LAST_APP_NAVIGATION_ENUM) { + opcode == Opcode.INVOKE_STATIC && + getReference()?.definingClass == navigationEnumClassName + } // Hook the creation of navigation tab views. - val drawableTabResult = PivotBarButtonsCreateDrawableViewFingerprint.resultOrThrow() - mutableMethod.injectHooksByFilter( - { - // Don't need to check for the opcode since the method reference already validates. - val reference = it.getReference() - reference?.definingClass == drawableTabResult.mutableClass.type && - reference.name == drawableTabResult.mutableMethod.name - }, - "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->navigationTabLoaded(Landroid/view/View;)V", - ) - - val imageResourceTabResult = PivotBarButtonsCreateResourceViewFingerprint.resultOrThrow() - mutableMethod.injectHooksByFilter( - { - val reference = it.getReference() - reference?.definingClass == imageResourceTabResult.mutableClass.type && - reference.name == imageResourceTabResult.mutableMethod.name - }, - "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->navigationImageResourceTabLoaded(Landroid/view/View;)V", - ) - } + val drawableTabMethod = PivotBarButtonsCreateDrawableViewFingerprint.resultOrThrow().mutableMethod + addHook(Hook.NAVIGATION_TAB_LOADED) { + MethodUtil.methodSignaturesMatch( + getReference() ?: return@addHook false, + drawableTabMethod, + ) + } - /** - * Callback for other patches. - */ - NavigationBarHookCallbackFingerprint.resultOrThrow().apply { - navigationTabCreatedCallbackMethod = mutableMethod + val imageResourceTabMethod = PivotBarButtonsCreateResourceViewFingerprint.resultOrThrow().method + addHook(Hook.NAVIGATION_IMAGE_RESOURCE_TAB_LOADED) { + MethodUtil.methodSignaturesMatch( + getReference() ?: return@addHook false, + imageResourceTabMethod, + ) + } } - /** - * Search bar. - */ + // 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 = implementation!!.instructions.indexOfFirst { - it.opcode == Opcode.INVOKE_VIRTUAL && - it.getReference()?.name == "setLayoutDirection" + val instructionIndex = indexOfFirstInstruction { + opcode == Opcode.INVOKE_VIRTUAL && getReference()?.name == "setLayoutDirection" } - val register = getInstruction(instructionIndex).registerC + + val viewRegister = getInstruction(instructionIndex).registerC + addInstruction( instructionIndex, - "invoke-static { v$register }, " + + "invoke-static { v$viewRegister }, " + "$INTEGRATIONS_CLASS_DESCRIPTOR->searchBarResultsViewLoaded(Landroid/view/View;)V", ) } } - fun hookNavigationButtonCreated(classDescriptor: String) { - navigationTabCreatedCallbackMethod.addInstruction( - 0, - "invoke-static { p0, p1 }, " + - "$classDescriptor->navigationTabCreated(${INTEGRATIONS_NAVIGATION_BUTTON_DESCRIPTOR}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/fingerprints/NavigationBarHookCallbackFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/fingerprints/NavigationBarHookCallbackFingerprint.kt index 6cc2f8aa3b..1d69dfe893 100644 --- 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 @@ -13,12 +13,9 @@ import com.android.tools.smali.dexlib2.AccessFlags internal object NavigationBarHookCallbackFingerprint : MethodFingerprint( accessFlags = AccessFlags.PRIVATE or AccessFlags.STATIC, returnType = "V", - parameters = listOf( - NavigationBarHookPatch.INTEGRATIONS_NAVIGATION_BUTTON_DESCRIPTOR, - "Landroid/view/View;" - ), + parameters = listOf(NavigationBarHookPatch.INTEGRATIONS_NAVIGATION_BUTTON_DESCRIPTOR, "Landroid/view/View;"), customFingerprint = { methodDef, _ -> - methodDef.name == "navigationTabCreatedCallback" - && methodDef.definingClass == NavigationBarHookPatch.INTEGRATIONS_CLASS_DESCRIPTOR - } -) \ No newline at end of file + methodDef.name == "navigationTabCreatedCallback" && + methodDef.definingClass == NavigationBarHookPatch.INTEGRATIONS_CLASS_DESCRIPTOR + }, +) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt index dddd02b5bf..2dd88e948d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt @@ -8,7 +8,6 @@ import com.android.tools.smali.dexlib2.builder.BuilderInstruction 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. @@ -23,7 +22,7 @@ internal object InjectionUtils { addInstruction( insertIndex, - hook.replace("REGISTER_INDEX", register.toString()) + hook.replace("REGISTER_INDEX", register.toString()), ) } @@ -32,7 +31,7 @@ internal object InjectionUtils { */ fun MutableMethod.injectHooksByFilter( insertionFilter: (BuilderInstruction) -> Boolean, - hook: String + hook: String, ) { val methodInstructions = implementation!!.instructions methodInstructions.filter(insertionFilter).let { filteredInstructions -> @@ -47,4 +46,4 @@ internal object InjectionUtils { } } } -} \ No newline at end of file +} From 4a0ce3bfc614943b7e623e4403d8281e348460bc Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Tue, 26 Mar 2024 20:10:24 +0100 Subject: [PATCH 23/26] remove obsolete class --- .../misc/navigation/utils/InjectionUtils.kt | 49 ------------------- 1 file changed, 49 deletions(-) delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt deleted file mode 100644 index 2dd88e948d..0000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/utils/InjectionUtils.kt +++ /dev/null @@ -1,49 +0,0 @@ -package app.revanced.patches.youtube.misc.navigation.utils - -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.patch.PatchException -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import com.android.tools.smali.dexlib2.builder.BuilderInstruction -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction - -internal object InjectionUtils { - - /** - * Injects an instruction into insertIndex of the hook. - * @param hook The hook to insert. - * @param insertIndex The index to insert the instruction at. - * a [OneRegisterInstruction] must be present before [insertIndex]. - */ - fun MutableMethod.injectHook(insertIndex: Int, hook: String) { - // Register to pass to the hook - val registerIndex = insertIndex - 1 // MOVE_RESULT_OBJECT is always the previous instruction - val register = getInstruction(registerIndex).registerA - - addInstruction( - insertIndex, - hook.replace("REGISTER_INDEX", register.toString()), - ) - } - - /** - * @param insertionFilter Filter that identifies method calls with a non void return type. - */ - fun MutableMethod.injectHooksByFilter( - insertionFilter: (BuilderInstruction) -> Boolean, - hook: String, - ) { - val methodInstructions = implementation!!.instructions - methodInstructions.filter(insertionFilter).let { filteredInstructions -> - if (filteredInstructions.isEmpty()) throw PatchException("Could not find insertion indexes") - filteredInstructions.forEach { - val index = methodInstructions.indexOf(it) - val register = (getInstruction(index + 1) as OneRegisterInstruction).registerA - addInstruction( - index + 2, - hook.replace("REGISTER_INDEX", register.toString()), - ) - } - } - } -} From 4f11db095405f25369f93755768b834407b7d646 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Wed, 27 Mar 2024 03:21:56 +0100 Subject: [PATCH 24/26] return to predicate --- .../youtube/misc/navigation/NavigationBarHookPatch.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 index 19c7a8dadf..2151ed88d9 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt @@ -66,17 +66,17 @@ object NavigationBarHookPatch : BytecodePatch( // Hook the creation of navigation tab views. val drawableTabMethod = PivotBarButtonsCreateDrawableViewFingerprint.resultOrThrow().mutableMethod - addHook(Hook.NAVIGATION_TAB_LOADED) { + addHook(Hook.NAVIGATION_TAB_LOADED) predicate@{ MethodUtil.methodSignaturesMatch( - getReference() ?: return@addHook false, + getReference() ?: return@predicate false, drawableTabMethod, ) } val imageResourceTabMethod = PivotBarButtonsCreateResourceViewFingerprint.resultOrThrow().method - addHook(Hook.NAVIGATION_IMAGE_RESOURCE_TAB_LOADED) { + addHook(Hook.NAVIGATION_IMAGE_RESOURCE_TAB_LOADED) predicate@{ MethodUtil.methodSignaturesMatch( - getReference() ?: return@addHook false, + getReference() ?: return@predicate false, imageResourceTabMethod, ) } From 6eae9421cd6c5d1a138be414b1fd0b65a7051c7a Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Wed, 27 Mar 2024 03:22:52 +0100 Subject: [PATCH 25/26] refactor --- .../youtube/misc/navigation/NavigationBarHookPatch.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) 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 index 2151ed88d9..675035253f 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt @@ -46,17 +46,19 @@ object NavigationBarHookPatch : BytecodePatch( override fun execute(context: BytecodeContext) { fun MutableMethod.addHook(hook: Hook, insertPredicate: Instruction.() -> Boolean) = getInstructions().filter(insertPredicate).forEach { - val register = (getInstruction(it.location.index + 1) as OneRegisterInstruction).registerA + val insertIndex = it.location.index + 2 + val register = getInstruction(insertIndex - 1).registerA addInstruction( - it.location.index + 2, + insertIndex, "invoke-static { v$register }, " + "$INTEGRATIONS_CLASS_DESCRIPTOR->${hook.methodName}(${hook.parameters})V", ) } - InitializeButtonsFingerprint.resolve(context, PivotBarConstructorFingerprint.resultOrThrow().classDef) - InitializeButtonsFingerprint.resultOrThrow().mutableMethod.apply { + 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) { From 70d5c7a20d3edd39732f016be009f554324ad479 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Wed, 27 Mar 2024 11:23:52 +0400 Subject: [PATCH 26/26] refactor: Throw an exception if the filter matched nothing --- .../youtube/misc/navigation/NavigationBarHookPatch.kt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) 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 index 675035253f..5b19cdc0a6 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt @@ -5,6 +5,7 @@ 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 @@ -44,17 +45,20 @@ object NavigationBarHookPatch : BytecodePatch( "Lapp/revanced/integrations/youtube/shared/NavigationBar\$NavigationButton;" override fun execute(context: BytecodeContext) { - fun MutableMethod.addHook(hook: Hook, insertPredicate: Instruction.() -> Boolean) = - getInstructions().filter(insertPredicate).forEach { + 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", + "$INTEGRATIONS_CLASS_DESCRIPTOR->${hook.methodName}(${hook.parameters})V", ) } + } InitializeButtonsFingerprint.apply { resolve(context, PivotBarConstructorFingerprint.resultOrThrow().classDef)