Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(YouTube - Hide layout components): Filter home/search results by keywords #2853

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
b8858f7
feat(YouTube): Add `Hide keyword content` patch
LisoUseInAIKyrios Feb 15, 2024
9cd5a63
refactor: move code into `HideLayoutComponents`
LisoUseInAIKyrios Mar 8, 2024
cc19666
feat: Support unicode keyword and custom filters
LisoUseInAIKyrios Mar 8, 2024
2c65188
fix: Use unsorted
LisoUseInAIKyrios Mar 8, 2024
f6bc936
adjust text
LisoUseInAIKyrios Mar 8, 2024
bc25b65
fix: Do not reset keywords or custom filter. Show a toast and leave …
LisoUseInAIKyrios Mar 9, 2024
dfc8e88
fix: Automatically filter capitalized first letter of each sentence.
LisoUseInAIKyrios Mar 9, 2024
86f24c8
refactor: Rename class
LisoUseInAIKyrios Mar 9, 2024
e82f6a2
fix: adjust settings text
LisoUseInAIKyrios Mar 10, 2024
bdf2bd7
Merge remote-tracking branch 'upstream/dev' into filter_keyword_content
LisoUseInAIKyrios Mar 11, 2024
d89490b
fix: adjust settings text
LisoUseInAIKyrios Mar 11, 2024
944b755
feat: Selective filtering of search/home/subscriptions
LisoUseInAIKyrios Mar 14, 2024
1e2f8a1
refactor: break apart NavigationButtonsPatch into subpatch
LisoUseInAIKyrios Mar 14, 2024
293ab6b
Merge remote-tracking branch 'upstream/dev' into filter_keyword_content
LisoUseInAIKyrios Mar 15, 2024
5368457
Adjust setting strings
LisoUseInAIKyrios Mar 17, 2024
83545b4
refactor: Use existing class name
LisoUseInAIKyrios Mar 17, 2024
75220ac
refactor: Simplify
LisoUseInAIKyrios Mar 17, 2024
05c03f3
refactor: Cleanup
LisoUseInAIKyrios Mar 19, 2024
5a89194
Merge remote-tracking branch 'upstream/dev' into filter_keyword_content
LisoUseInAIKyrios Mar 19, 2024
b8aa8ea
fix: Detect some keywords that will always hide all videos
LisoUseInAIKyrios Mar 19, 2024
2094b9d
fix: Adjust settings text
LisoUseInAIKyrios Mar 21, 2024
0de51bf
fix: Hook the 'You' library tab
LisoUseInAIKyrios Mar 21, 2024
1db7ddb
refactor: No fingerprint opcodes. Changes needed for future YT 19.10…
LisoUseInAIKyrios Mar 24, 2024
79154f2
Merge remote-tracking branch 'upstream/dev' into filter_keyword_content
LisoUseInAIKyrios Mar 26, 2024
001d210
adjust description
oSumAtrIX Mar 26, 2024
c7d18e2
refactor
oSumAtrIX Mar 26, 2024
4a0ce3b
remove obsolete class
oSumAtrIX Mar 26, 2024
4f11db0
return to predicate
oSumAtrIX Mar 27, 2024
6eae942
refactor
oSumAtrIX Mar 27, 2024
70d5c7a
refactor: Throw an exception if the filter matched nothing
LisoUseInAIKyrios Mar 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions api/revanced-patches.api
Original file line number Diff line number Diff line change
Expand Up @@ -1609,6 +1609,13 @@ public final class app/revanced/patches/youtube/misc/minimizedplayback/Minimized
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}

public final class app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
public final fun getHookNavigationButtonCreated ()Lkotlin/jvm/functions/Function1;
}

public final class app/revanced/patches/youtube/misc/playercontrols/BottomControlsResourcePatch : app/revanced/patcher/patch/ResourcePatch, java/io/Closeable {
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/playercontrols/BottomControlsResourcePatch;
public final fun addControls (Ljava/lang/String;)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import app.revanced.patches.all.misc.resources.AddResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.layout.buttons.navigation.fingerprints.*
import app.revanced.patches.youtube.layout.buttons.navigation.utils.InjectionUtils.REGISTER_TEMPLATE_REPLACEMENT
import app.revanced.patches.youtube.layout.buttons.navigation.utils.InjectionUtils.injectHook
import app.revanced.patches.youtube.layout.buttons.navigation.fingerprints.ANDROID_AUTOMOTIVE_STRING
import app.revanced.patches.youtube.layout.buttons.navigation.fingerprints.AddCreateButtonViewFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
Expand All @@ -24,8 +24,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
dependencies = [
IntegrationsPatch::class,
SettingsPatch::class,
ResolvePivotBarFingerprintsPatch::class,
AddResourcesPatch::class,
NavigationBarHookPatch::class,
],
compatiblePackages = [
CompatiblePackage(
Expand All @@ -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",
],
),
],
Expand Down Expand Up @@ -76,61 +76,16 @@ object NavigationButtonsPatch : BytecodePatch(
),
)

/*
* Resolve fingerprints
*/

val initializeButtonsResult = InitializeButtonsFingerprint.result!!

val fingerprintResults =
arrayOf(PivotBarEnumFingerprint, PivotBarButtonsViewFingerprint)
.onEach {
if (!it.resolve(
context,
initializeButtonsResult.mutableMethod,
initializeButtonsResult.mutableClass,
)
) {
throw it.exception
}
}
.map { it.result!!.scanResult.patternScanResult!! }

val enumScanResult = fingerprintResults[0]
val buttonViewResult = fingerprintResults[1]

val enumHookInsertIndex = enumScanResult.startIndex + 2
val buttonHookInsertIndex = buttonViewResult.endIndex

/*
* Inject hooks
*/

val enumHook = "sput-object v$REGISTER_TEMPLATE_REPLACEMENT, " +
"$INTEGRATIONS_CLASS_DESCRIPTOR->lastNavigationButton:Ljava/lang/Enum;"
val buttonHook = "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " +
"$INTEGRATIONS_CLASS_DESCRIPTOR->hideButton(Landroid/view/View;)V"

// Inject bottom to top to not mess up the indices
mapOf(
buttonHook to buttonHookInsertIndex,
enumHook to enumHookInsertIndex,
).forEach { (hook, insertIndex) ->
initializeButtonsResult.mutableMethod.injectHook(hook, insertIndex)
}

/*
* Hide create or switch it with notifications buttons.
*/

// Switch create with notifications button.
AddCreateButtonViewFingerprint.result?.let {
it.mutableMethod.apply {
val stringIndex = it.scanResult.stringsScanResult!!.matches.find { match ->
match.string == ANDROID_AUTOMOTIVE_STRING
}!!.index

val conditionalCheckIndex = stringIndex - 1
val conditionRegister = getInstruction<OneRegisterInstruction>(conditionalCheckIndex).registerA
val conditionRegister =
getInstruction<OneRegisterInstruction>(conditionalCheckIndex).registerA

addInstructions(
conditionalCheckIndex,
Expand All @@ -142,26 +97,7 @@ object NavigationButtonsPatch : BytecodePatch(
}
} ?: throw AddCreateButtonViewFingerprint.exception

/*
* Resolve fingerprints
*/

InitializeButtonsFingerprint.result!!.let {
if (!PivotBarCreateButtonViewFingerprint.resolve(context, it.mutableMethod, it.mutableClass)) {
throw PivotBarCreateButtonViewFingerprint.exception
}
}

PivotBarCreateButtonViewFingerprint.result!!.apply {
val insertIndex = scanResult.patternScanResult!!.endIndex

/*
* Inject hooks
*/
val hook = "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " +
"$INTEGRATIONS_CLASS_DESCRIPTOR->hideCreateButton(Landroid/view/View;)V"

mutableMethod.injectHook(hook, insertIndex)
}
// Hook navigation button created, in order to hide them.
NavigationBarHookPatch.hookNavigationButtonCreated(INTEGRATIONS_CLASS_DESCRIPTOR)
}
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.all.misc.resources.AddResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.InputType
import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
Expand All @@ -20,8 +21,10 @@ import app.revanced.patches.youtube.layout.hide.general.fingerprints.ParseElemen
import app.revanced.patches.youtube.layout.hide.general.fingerprints.PlayerOverlayFingerprint
import app.revanced.patches.youtube.layout.hide.general.fingerprints.ShowWatermarkFingerprint
import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch
import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.exception
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
Expand All @@ -33,6 +36,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
LithoFilterPatch::class,
SettingsPatch::class,
AddResourcesPatch::class,
NavigationBarHookPatch::class,
PlayerTypeHookPatch::class // Used by Keyword Content filter.
],
compatiblePackages = [
CompatiblePackage(
Expand Down Expand Up @@ -69,6 +74,8 @@ object HideLayoutComponentsPatch : BytecodePatch(
"Lapp/revanced/integrations/youtube/patches/components/DescriptionComponentsFilter;"
private const val CUSTOM_FILTER_CLASS_NAME =
"Lapp/revanced/integrations/youtube/patches/components/CustomFilter;"
private const val KEYWORD_FILTER_CLASS_NAME =
"Lapp/revanced/integrations/youtube/patches/components/KeywordContentFilter;"

override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
Expand Down Expand Up @@ -117,6 +124,20 @@ object HideLayoutComponentsPatch : BytecodePatch(
SwitchPreference("revanced_hide_search_result_shelf_header"),
)

SettingsPatch.PreferenceScreen.FEED.addPreferences(
PreferenceScreen(
key = "revanced_hide_keyword_content_screen",
sorting = Sorting.UNSORTED,
preferences = setOf(
SwitchPreference("revanced_hide_keyword_content_home"),
SwitchPreference("revanced_hide_keyword_content_subscriptions"),
SwitchPreference("revanced_hide_keyword_content_search"),
TextPreference("revanced_hide_keyword_content_phrases", inputType = InputType.TEXT_MULTI_LINE),
NonInteractivePreference("revanced_hide_keyword_content_about")
)
)
)

SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences(
SwitchPreference("revanced_hide_gray_separator"),
PreferenceScreen(
Expand All @@ -136,19 +157,19 @@ object HideLayoutComponentsPatch : BytecodePatch(

LithoFilterPatch.addFilter(LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR)
LithoFilterPatch.addFilter(DESCRIPTION_COMPONENTS_FILTER_CLASS_NAME)
LithoFilterPatch.addFilter(KEYWORD_FILTER_CLASS_NAME)
LithoFilterPatch.addFilter(CUSTOM_FILTER_CLASS_NAME)

// region Mix playlists

ParseElementFromBufferFingerprint.result?.let { result ->
val returnEmptyComponentInstruction =
result.mutableMethod.getInstructions().last { it.opcode == Opcode.INVOKE_STATIC }
ParseElementFromBufferFingerprint.resultOrThrow().let { result ->
val consumeByteBufferIndex = result.scanResult.patternScanResult!!.startIndex

result.mutableMethod.apply {
val consumeByteBufferIndex = result.scanResult.patternScanResult!!.startIndex
val conversionContextRegister =
getInstruction<TwoRegisterInstruction>(consumeByteBufferIndex - 2).registerA
val byteBufferRegister = getInstruction<FiveRegisterInstruction>(consumeByteBufferIndex).registerD
val returnEmptyComponentInstruction = getInstructions().last { it.opcode == Opcode.INVOKE_STATIC }

addInstructionsWithLabels(
consumeByteBufferIndex,
Expand All @@ -160,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)
Expand All @@ -179,7 +200,7 @@ object HideLayoutComponentsPatch : BytecodePatch(
move-result p2
""",
)
} ?: throw ShowWatermarkFingerprint.exception
}

// endregion
}
Expand Down
Loading
Loading