mirror of
https://github.com/revanced/revanced-patches
synced 2024-12-01 08:32:53 +01:00
feat: settings
patch framework (#266)
This commit is contained in:
parent
1866d84251
commit
084a99bc6f
@ -23,6 +23,9 @@ import app.revanced.patches.youtube.ad.general.bytecode.extensions.MethodExtensi
|
||||
import app.revanced.patches.youtube.ad.general.bytecode.utils.MethodUtils.createMutableMethod
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.builder.MutableMethodImplementation
|
||||
import org.jf.dexlib2.builder.instruction.*
|
||||
@ -38,7 +41,7 @@ import org.jf.dexlib2.iface.reference.StringReference
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
|
||||
|
||||
@Patch
|
||||
@DependsOn([ResourceIdMappingProviderResourcePatch::class, IntegrationsPatch::class])
|
||||
@DependsOn([ResourceIdMappingProviderResourcePatch::class, IntegrationsPatch::class, SettingsPatch::class])
|
||||
@Name("general-ads")
|
||||
@Description("Removes general ads.")
|
||||
@GeneralAdsCompatibility
|
||||
@ -68,6 +71,135 @@ class GeneralBytecodeAdsPatch : BytecodePatch() {
|
||||
)
|
||||
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.ADS.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_home_ads_enabled",
|
||||
StringResource("revanced_home_ads_enabled_title", "Hide home ads"),
|
||||
true,
|
||||
StringResource("revanced_home_ads_enabled_summary_on", "Home ads are shown"),
|
||||
StringResource("revanced_home_ads_enabled_summary_off", "Home ads are hidden")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_adremover_ad_removal",
|
||||
StringResource("revanced_adremover_ad_removal_enabled_title", "Remove general ads"),
|
||||
true,
|
||||
StringResource("revanced_adremover_ad_removal_enabled_summary_on", "General ads are hidden"),
|
||||
StringResource("revanced_adremover_ad_removal_enabled_summary_off", "General ads are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_adremover_merchandise",
|
||||
StringResource("revanced_adremover_merchandise_enabled_title", "Remove merchandise banners"),
|
||||
true,
|
||||
StringResource("revanced_adremover_merchandise_enabled_summary_on", "Merchandise banners are hidden"),
|
||||
StringResource("revanced_adremover_merchandise_enabled_summary_off", "Merchandise banners are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_adremover_community_posts_removal",
|
||||
StringResource("revanced_adremover_community_posts_enabled_title", "Remove community posts"),
|
||||
true,
|
||||
StringResource("revanced_adremover_community_posts_enabled_summary_on", "Community posts are hidden"),
|
||||
StringResource("revanced_adremover_community_posts_enabled_summary_off", "Community posts are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_adremover_compact_banner_removal",
|
||||
StringResource("revanced_adremover_compact_banner_enabled_title", "Remove compact banners"),
|
||||
true,
|
||||
StringResource("revanced_adremover_compact_banner_enabled_summary_on", "Compact banners are hidden"),
|
||||
StringResource("revanced_adremover_compact_banner_enabled_summary_off", "Compact banners are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_adremover_comments_removal",
|
||||
StringResource("revanced_adremover_comments_enabled_title", "Remove comments section"),
|
||||
false,
|
||||
StringResource("revanced_adremover_comments_enabled_summary_on", "Comment section is hidden"),
|
||||
StringResource("revanced_adremover_comments_enabled_summary_off", "Comment section is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_adremover_movie",
|
||||
StringResource("revanced_adremover_movie_enabled_title", "Remove movies section"),
|
||||
true,
|
||||
StringResource("revanced_adremover_movie_enabled_summary_on", "Movies section is hidden"),
|
||||
StringResource("revanced_adremover_movie_enabled_summary_off", "Movies section is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_adremover_feed_survey",
|
||||
StringResource("revanced_adremover_feed_survey_enabled_title", "Remove feed surveys"),
|
||||
true,
|
||||
StringResource("revanced_adremover_feed_survey_enabled_summary_on", "Feed surveys are hidden"),
|
||||
StringResource("revanced_adremover_feed_survey_enabled_summary_off", "Feed surveys are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_adremover_shorts_shelf",
|
||||
StringResource("revanced_adremover_shorts_shelf_enabled_title", "Remove shorts shelf"),
|
||||
true,
|
||||
StringResource("revanced_adremover_shorts_shelf_enabled_summary_on", "Shorts shelves are hidden"),
|
||||
StringResource("revanced_adremover_shorts_shelf_enabled_summary_off", "Shorts shelves are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_adremover_community_guidelines",
|
||||
StringResource("revanced_adremover_community_guidelines_enabled_title", "Remove community guidelines"),
|
||||
true,
|
||||
StringResource("revanced_adremover_community_guidelines_enabled_summary_on", "Community guidelines are hidden"),
|
||||
StringResource("revanced_adremover_community_guidelines_enabled_summary_off", "Community guidelines are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_adremover_emergency_box_removal",
|
||||
StringResource("revanced_adremover_emergency_box_enabled_title", "Remove emergency boxes"),
|
||||
true,
|
||||
StringResource("revanced_adremover_emergency_box_enabled_summary_on", "Emergency boxes are hidden"),
|
||||
StringResource("revanced_adremover_emergency_box_enabled_summary_off", "Emergency boxes are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_adremover_info_panel",
|
||||
StringResource("revanced_adremover_info_panel_enabled_title", "Remove info panels"),
|
||||
true,
|
||||
StringResource("revanced_adremover_info_panel_enabled_summary_on", "Merchandise banners are hidden"),
|
||||
StringResource("revanced_adremover_info_panel_enabled_summary_off", "Merchandise banners are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_adremover_medical_panel",
|
||||
StringResource("revanced_adremover_medical_panel_enabled_title", "Remove medical panels"),
|
||||
true,
|
||||
StringResource("revanced_adremover_medical_panel_enabled_summary_on", "Medical panels are hidden"),
|
||||
StringResource("revanced_adremover_medical_panel_enabled_summary_off", "Medical panels are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_adremover_paid_content",
|
||||
StringResource("revanced_adremover_paid_content_enabled_title", "Remove paid content"),
|
||||
true,
|
||||
StringResource("revanced_adremover_paid_content_enabled_summary_on", "Paid content is hidden"),
|
||||
StringResource("revanced_adremover_paid_content_enabled_summary_off", "Paid content is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_adremover_suggested",
|
||||
StringResource("revanced_adremover_suggested_enabled_title", "Remove personal suggestions"),
|
||||
true,
|
||||
StringResource("revanced_adremover_suggested_enabled_summary_on", "Personal suggestions are hidden"),
|
||||
StringResource("revanced_adremover_suggested_enabled_summary_off", "Personal suggestions are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_adremover_hide_suggestions",
|
||||
StringResource("revanced_adremover_hide_suggestions_enabled_title", "Hide suggestions"),
|
||||
true,
|
||||
StringResource("revanced_adremover_hide_suggestions_enabled_summary_on", "Suggestions are hidden"),
|
||||
StringResource("revanced_adremover_hide_suggestions_enabled_summary_off", "Suggestions are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_adremover_hide_latest_posts",
|
||||
StringResource("revanced_adremover_hide_latest_posts_enabled_title", "Hide latest posts"),
|
||||
true,
|
||||
StringResource("revanced_adremover_hide_latest_posts_enabled_summary_on", "Latest posts are hidden"),
|
||||
StringResource("revanced_adremover_hide_latest_posts_enabled_summary_off", "Latest posts are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_adremover_hide_channel_guidelines",
|
||||
StringResource("revanced_adremover_hide_channel_guidelines_enabled_title", "Hide channel guidelines"),
|
||||
true,
|
||||
StringResource("revanced_adremover_hide_channel_guidelines_enabled_summary_on", "Channel guidelines are hidden"),
|
||||
StringResource("revanced_adremover_hide_channel_guidelines_enabled_summary_off", "Channel guidelines are shown")
|
||||
),
|
||||
)
|
||||
|
||||
// iterating through all classes is expensive
|
||||
for (classDef in data.classes) {
|
||||
var mutableClass: MutableClass? = null
|
||||
|
@ -16,10 +16,13 @@ import app.revanced.patches.youtube.ad.infocardsuggestions.annotations.HideInfoc
|
||||
import app.revanced.patches.youtube.ad.infocardsuggestions.fingerprints.HideInfocardSuggestionsFingerprint
|
||||
import app.revanced.patches.youtube.ad.infocardsuggestions.fingerprints.HideInfocardSuggestionsParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
|
||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
|
||||
|
||||
@Patch
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
|
||||
@Name("hide-infocard-suggestions")
|
||||
@Description("Hides infocards in videos.")
|
||||
@HideInfocardSuggestionsCompatibility
|
||||
@ -30,6 +33,16 @@ class HideInfocardSuggestionsPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.ADS.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_info_cards_enabled",
|
||||
StringResource("revanced_info_cards_enabled_title", "Show info-cards"),
|
||||
false,
|
||||
StringResource("revanced_info_cards_enabled_summary_on", "Info-cards are shown"),
|
||||
StringResource("revanced_info_cards_enabled_summary_off", "Info-cards are hidden")
|
||||
)
|
||||
)
|
||||
|
||||
val parentResult = HideInfocardSuggestionsParentFingerprint.result
|
||||
?: return PatchResultError("Parent fingerprint not resolved!")
|
||||
|
||||
|
@ -15,9 +15,12 @@ import app.revanced.patches.youtube.ad.video.annotations.VideoAdsCompatibility
|
||||
import app.revanced.patches.youtube.ad.video.fingerprints.ShowVideoAdsConstructorFingerprint
|
||||
import app.revanced.patches.youtube.ad.video.fingerprints.ShowVideoAdsFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
|
||||
|
||||
@Patch
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
|
||||
@Name("video-ads")
|
||||
@Description("Removes ads in the video player.")
|
||||
@VideoAdsCompatibility
|
||||
@ -28,7 +31,19 @@ class VideoAdsPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
ShowVideoAdsFingerprint.resolve(data, ShowVideoAdsConstructorFingerprint.result!!.classDef)
|
||||
SettingsPatch.PreferenceScreen.ADS.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_video_ads_enabled",
|
||||
StringResource("revanced_video_ads_enabled_title", "Hide video ads"),
|
||||
true,
|
||||
StringResource("revanced_video_ads_enabled_summary_on", "Video ads are hidden"),
|
||||
StringResource("revanced_video_ads_enabled_summary_off", "Video ads are shown")
|
||||
)
|
||||
)
|
||||
|
||||
ShowVideoAdsFingerprint.resolve(
|
||||
data, ShowVideoAdsConstructorFingerprint.result!!.classDef
|
||||
)
|
||||
|
||||
// Override the parameter by calling shouldShowAds and setting the parameter to the result
|
||||
ShowVideoAdsFingerprint.result!!.mutableMethod.addInstructions(
|
||||
@ -40,4 +55,4 @@ class VideoAdsPatch : BytecodePatch(
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,9 @@ import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappin
|
||||
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.SeekbarTappingFingerprint
|
||||
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.SeekbarTappingParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
|
||||
import org.jf.dexlib2.iface.Method
|
||||
@ -22,7 +25,7 @@ import org.jf.dexlib2.iface.instruction.formats.Instruction11n
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
||||
|
||||
@Patch
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
|
||||
@Name("seekbar-tapping")
|
||||
@Description("Enables tap-to-seek on the seekbar of the video player.")
|
||||
@SeekbarTappingCompatibility
|
||||
@ -33,6 +36,16 @@ class EnableSeekbarTappingPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_enable_tap_seeking",
|
||||
StringResource("revanced_seekbar_tapping_enabled_title", "Enable seekbar tapping"),
|
||||
true,
|
||||
StringResource("revanced_seekbar_tapping_summary_on", "Seekbar tapping is enabled"),
|
||||
StringResource("revanced_seekbar_tapping_summary_off", "Seekbar tapping is disabled")
|
||||
)
|
||||
)
|
||||
|
||||
var result = SeekbarTappingParentFingerprint.result!!
|
||||
|
||||
val tapSeekMethods = mutableMapOf<String, Method>()
|
||||
@ -42,7 +55,7 @@ class EnableSeekbarTappingPatch : BytecodePatch(
|
||||
if (it.implementation == null) continue
|
||||
|
||||
val instructions = it.implementation!!.instructions
|
||||
// here we make sure we actually find the method because it has more then 7 instructions
|
||||
// here we make sure we actually find the method because it has more than 7 instructions
|
||||
if (instructions.count() < 7) continue
|
||||
|
||||
// we know that the 7th instruction has the opcode CONST_4
|
||||
|
@ -65,5 +65,4 @@ class SwipeControlsBytecodePatch : BytecodePatch(
|
||||
}
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -6,14 +6,91 @@ import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.ResourceData
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.*
|
||||
|
||||
@Name("swipe-controls-resource-patch")
|
||||
@DependsOn([SettingsPatch::class])
|
||||
@SwipeControlsCompatibility
|
||||
@Version("0.0.1")
|
||||
class SwipeControlsResourcePatch : ResourcePatch() {
|
||||
override fun execute(data: ResourceData): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
|
||||
PreferenceScreen(
|
||||
"revanced_swipe_controls", StringResource("revanced_swipe_controls_title", "Swipe controls"), listOf(
|
||||
SwitchPreference(
|
||||
"revanced_enable_swipe_brightness",
|
||||
StringResource("revanced_swipe_brightness_enabled_title", "Enable brightness gesture"),
|
||||
true,
|
||||
StringResource("revanced_swipe_brightness_summary_on", "Brightness swipe is enabled"),
|
||||
StringResource("revanced_swipe_brightness_summary_off", "Brightness swipe is disabled")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_enable_swipe_volume",
|
||||
StringResource("revanced_swipe_volume_enabled_title", "Enable volume gesture"),
|
||||
true,
|
||||
StringResource("revanced_swipe_volume_summary_on", "Volume swipe is enabled"),
|
||||
StringResource("revanced_swipe_volume_summary_off", "Volume swipe is disabled")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_enable_press_to_swipe",
|
||||
StringResource("revanced_press_to_swipe_enabled_title", "Enable press-to-swipe gesture"),
|
||||
false,
|
||||
StringResource("revanced_press_to_swipe_summary_on", "Press-to-swipe is enabled"),
|
||||
StringResource("revanced_press_to_swipe_summary_off", "Press-to-swipe is disabled")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_enable_swipe_haptic_feedback",
|
||||
StringResource("revanced_swipe_haptic_feedback_enabled_title", "Enable haptic feedback"),
|
||||
true,
|
||||
StringResource("revanced_swipe_haptic_feedback_summary_on", "Haptic feedback is enabled"),
|
||||
StringResource("revanced_swipe_haptic_feedback_summary_off", "Haptic feedback is disabled")
|
||||
),
|
||||
TextPreference(
|
||||
"revanced_swipe_overlay_timeout",
|
||||
StringResource("revanced_swipe_overlay_timeout_title", "Swipe overlay timeout"),
|
||||
InputType.NUMBER,
|
||||
"500",
|
||||
StringResource(
|
||||
"revanced_swipe_overlay_timeout_summary",
|
||||
"The amount of milliseconds the overlay is visible"
|
||||
)
|
||||
),
|
||||
TextPreference(
|
||||
"revanced_swipe_overlay_text_size",
|
||||
StringResource("revanced_swipe_overlay_text_size_title", "Swipe overlay text size"),
|
||||
InputType.NUMBER,
|
||||
"22",
|
||||
StringResource("revanced_swipe_overlay_text_size_summary", "The text size for swipe overlay")
|
||||
),
|
||||
TextPreference(
|
||||
"revanced_swipe_overlay_background_alpha",
|
||||
StringResource("revanced_swipe_overlay_background_alpha_title", "Swipe background visibility"),
|
||||
InputType.NUMBER,
|
||||
"127",
|
||||
StringResource(
|
||||
"revanced_swipe_overlay_background_alpha_summary",
|
||||
"The visibility of swipe overlay background"
|
||||
)
|
||||
),
|
||||
TextPreference(
|
||||
"revanced_swipe_magnitude_threshold",
|
||||
StringResource("revanced_swipe_magnitude_threshold_title", "Swipe magnitude threshold"),
|
||||
InputType.NUMBER,
|
||||
"30",
|
||||
StringResource(
|
||||
"revanced_swipe_magnitude_threshold_summary",
|
||||
"The amount of threshold for swipe to occur"
|
||||
)
|
||||
)
|
||||
),
|
||||
StringResource("revanced_swipe_controls_summary","Control volume and brightness")
|
||||
)
|
||||
)
|
||||
|
||||
val resourcesDir = "swipecontrols"
|
||||
|
||||
data.injectResources(
|
||||
|
@ -14,10 +14,9 @@ import org.jf.dexlib2.Opcode
|
||||
@MatchingMethod(
|
||||
"LWillAutonavInformer;", "k"
|
||||
)
|
||||
@FuzzyPatternScanMethod(2)
|
||||
@AutoplayButtonCompatibility
|
||||
@Version("0.0.1")
|
||||
object AutonavInformerFingerprint : MethodFingerprint(
|
||||
object AutoNavInformerFingerprint : MethodFingerprint(
|
||||
"Z",
|
||||
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
null,
|
||||
@ -31,4 +30,4 @@ object AutonavInformerFingerprint : MethodFingerprint(
|
||||
),
|
||||
null,
|
||||
{ it.definingClass.endsWith("WillAutonavInformer;") }
|
||||
)
|
||||
)
|
@ -2,31 +2,19 @@ package app.revanced.patches.youtube.layout.autoplaybutton.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.layout.autoplaybutton.annotations.AutoplayButtonCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
@Name("layout-constructor-fingerprint")
|
||||
@MatchingMethod(
|
||||
"LYouTubeControlsOverlay;", "F"
|
||||
)
|
||||
@FuzzyPatternScanMethod(2)
|
||||
@AutoplayButtonCompatibility
|
||||
@Version("0.0.1")
|
||||
object LayoutConstructorFingerprint : MethodFingerprint(
|
||||
"V",
|
||||
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
null,
|
||||
listOf(
|
||||
Opcode.CONST,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CHECK_CAST,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
),
|
||||
listOf("1.0x")
|
||||
)
|
||||
null, null, null, null, listOf("1.0x"),
|
||||
{ methodDef ->
|
||||
methodDef.definingClass.endsWith("YouTubeControlsOverlay;")
|
||||
}
|
||||
)
|
@ -1,88 +0,0 @@
|
||||
package app.revanced.patches.youtube.layout.autoplaybutton.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.removeInstruction
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.youtube.layout.autoplaybutton.annotations.AutoplayButtonCompatibility
|
||||
import app.revanced.patches.youtube.layout.autoplaybutton.fingerprints.AutonavInformerFingerprint
|
||||
import app.revanced.patches.youtube.layout.autoplaybutton.fingerprints.LayoutConstructorFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
|
||||
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
||||
|
||||
@Patch
|
||||
@DependsOn([ResourceIdMappingProviderResourcePatch::class, IntegrationsPatch::class])
|
||||
@Name("hide-autoplay-button")
|
||||
@Description("Hides the autoplay button in the video player.")
|
||||
@AutoplayButtonCompatibility
|
||||
@Version("0.0.1")
|
||||
class HideAutoplayButton : BytecodePatch(
|
||||
listOf(
|
||||
LayoutConstructorFingerprint, AutonavInformerFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
val layoutGenMethod = LayoutConstructorFingerprint.result!!.mutableMethod
|
||||
|
||||
val autonavToggle =
|
||||
ResourceIdMappingProviderResourcePatch.resourceMappings.single { it.type == "id" && it.name == "autonav_toggle" }
|
||||
val autonavPreviewStub =
|
||||
ResourceIdMappingProviderResourcePatch.resourceMappings.single { it.type == "id" && it.name == "autonav_preview_stub" }
|
||||
|
||||
val instructions = layoutGenMethod.implementation!!.instructions
|
||||
|
||||
val autonavToggleConstIndex =
|
||||
instructions.indexOfFirst { (it as? WideLiteralInstruction)?.wideLiteral == autonavToggle.id } + 4
|
||||
val autonavPreviewStubConstIndex =
|
||||
instructions.indexOfFirst { (it as? WideLiteralInstruction)?.wideLiteral == autonavPreviewStub.id } + 4
|
||||
|
||||
injectIfBranch(layoutGenMethod, autonavToggleConstIndex)
|
||||
injectIfBranch(layoutGenMethod, autonavPreviewStubConstIndex)
|
||||
|
||||
val autonavInformerMethod = AutonavInformerFingerprint.result!!.mutableMethod
|
||||
|
||||
//force disable autoplay since it's hard to do without the button
|
||||
autonavInformerMethod.addInstructions(
|
||||
0, """
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/HideAutoplayButtonPatch;->isButtonShown()Z
|
||||
move-result v0
|
||||
if-nez v0, :hidden
|
||||
const/4 v0, 0x0
|
||||
return v0
|
||||
:hidden
|
||||
nop
|
||||
"""
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
private fun injectIfBranch(method: MutableMethod, index: Int) {
|
||||
val instructions = method.implementation!!.instructions
|
||||
val insn = (instructions.get(index) as? Instruction35c)!!
|
||||
val methodToCall = insn.reference.toString()
|
||||
|
||||
//remove the invoke-virtual because we want to put it in an if-statement
|
||||
method.removeInstruction(index)
|
||||
method.addInstructions(
|
||||
index, """
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/HideAutoplayButtonPatch;->isButtonShown()Z
|
||||
move-result v11
|
||||
if-eqz v11, :hidebutton
|
||||
invoke-virtual {v${insn.registerC}, v${insn.registerD}, v${insn.registerE}}, $methodToCall
|
||||
:hidebutton
|
||||
nop
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package app.revanced.patches.youtube.layout.autoplaybutton.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.layout.autoplaybutton.annotations.AutoplayButtonCompatibility
|
||||
import app.revanced.patches.youtube.layout.autoplaybutton.fingerprints.AutoNavInformerFingerprint
|
||||
import app.revanced.patches.youtube.layout.autoplaybutton.fingerprints.LayoutConstructorFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
|
||||
import org.jf.dexlib2.iface.instruction.Instruction
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||
import org.jf.dexlib2.iface.reference.MethodReference
|
||||
|
||||
@Patch
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class, ResourceIdMappingProviderResourcePatch::class])
|
||||
@Name("hide-autoplay-button")
|
||||
@Description("Hides the autoplay button in the video player.")
|
||||
@AutoplayButtonCompatibility
|
||||
@Version("0.0.1")
|
||||
class HideAutoplayButtonPatch : BytecodePatch(
|
||||
listOf(
|
||||
LayoutConstructorFingerprint, AutoNavInformerFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_autoplay_button_enabled",
|
||||
StringResource("revanced_autoplay_button_enabled_title", "Show autoplay button"),
|
||||
false,
|
||||
StringResource("revanced_autoplay_button_summary_on", "Autoplay button is shown"),
|
||||
StringResource("revanced_autoplay_button_summary_off", "Autoplay button is hidden")
|
||||
)
|
||||
)
|
||||
|
||||
val autoNavInformerMethod = AutoNavInformerFingerprint.result!!.mutableMethod
|
||||
|
||||
val layoutGenMethodResult = LayoutConstructorFingerprint.result!!
|
||||
val layoutGenMethod = layoutGenMethodResult.mutableMethod
|
||||
val layoutGenMethodInstructions = layoutGenMethod.implementation!!.instructions
|
||||
|
||||
// resolve the offsets such as ...
|
||||
val autoNavPreviewStubId = ResourceIdMappingProviderResourcePatch.resourceMappings.single {
|
||||
it.name == "autonav_preview_stub"
|
||||
}.id
|
||||
// where to insert the branch instructions and ...
|
||||
val insertIndex = layoutGenMethodInstructions.indexOfFirst {
|
||||
(it as? WideLiteralInstruction)?.wideLiteral == autoNavPreviewStubId
|
||||
}
|
||||
// where to branch away
|
||||
val branchIndex = layoutGenMethodInstructions.subList(insertIndex + 1, layoutGenMethodInstructions.size - 1).indexOfFirst {
|
||||
((it as? ReferenceInstruction)?.reference as? MethodReference)?.name == "addOnLayoutChangeListener"
|
||||
} + 2
|
||||
|
||||
val jumpInstruction = layoutGenMethodInstructions[insertIndex + branchIndex] as Instruction
|
||||
layoutGenMethod.addInstructions(
|
||||
insertIndex, """
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/HideAutoplayButtonPatch;->isButtonShown()Z
|
||||
move-result v11
|
||||
if-eqz v11, :hidden
|
||||
""", listOf(ExternalLabel("hidden", jumpInstruction))
|
||||
)
|
||||
|
||||
//force disable autoplay since it's hard to do without the button
|
||||
autoNavInformerMethod.addInstructions(
|
||||
0, """
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/HideAutoplayButtonPatch;->isButtonShown()Z
|
||||
move-result v0
|
||||
if-nez v0, :hidden
|
||||
const/4 v0, 0x0
|
||||
return v0
|
||||
:hidden
|
||||
nop
|
||||
"""
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
@ -12,15 +12,28 @@ import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patches.youtube.layout.castbutton.annotations.CastButtonCompatibility
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
|
||||
|
||||
@Patch
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
|
||||
@Name("hide-cast-button")
|
||||
@Description("Hides the cast button in the video player.")
|
||||
@CastButtonCompatibility
|
||||
@Version("0.0.1")
|
||||
class HideCastButtonPatch : BytecodePatch() {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_cast_button_enabled",
|
||||
StringResource("revanced_cast_button_enabled_title", "Show cast button"),
|
||||
false,
|
||||
StringResource("revanced_cast_button_summary_on", "Cast button is shown"),
|
||||
StringResource("revanced_cast_button_summary_off", "Cast button is hidden")
|
||||
)
|
||||
)
|
||||
|
||||
data.classes.forEach { classDef ->
|
||||
classDef.methods.forEach { method ->
|
||||
if (classDef.type.endsWith("MediaRouteButton;") && method.name == "setVisibility") {
|
||||
|
@ -15,6 +15,9 @@ import app.revanced.patches.youtube.layout.createbutton.annotations.CreateButton
|
||||
import app.revanced.patches.youtube.layout.createbutton.fingerprints.CreateButtonFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
@ -22,7 +25,7 @@ import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||
import org.jf.dexlib2.iface.reference.MethodReference
|
||||
|
||||
@Patch
|
||||
@DependsOn([IntegrationsPatch::class, ResourceIdMappingProviderResourcePatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, ResourceIdMappingProviderResourcePatch::class, SettingsPatch::class])
|
||||
@Name("disable-create-button")
|
||||
@Description("Hides the create button in the navigation bar.")
|
||||
@CreateButtonCompatibility
|
||||
@ -33,6 +36,16 @@ class CreateButtonRemoverPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_create_button_enabled",
|
||||
StringResource("revanced_create_button_enabled_title", "Show create button"),
|
||||
false,
|
||||
StringResource("revanced_create_button_summary_on", "Create button is shown."),
|
||||
StringResource("revanced_create_button_summary_off", "Create button is hidden.")
|
||||
)
|
||||
)
|
||||
|
||||
val result = CreateButtonFingerprint.result!!
|
||||
|
||||
// Get the required register which holds the view object we need to pass to the method hideCreateButton
|
||||
|
@ -17,10 +17,13 @@ import app.revanced.patches.youtube.layout.fullscreenpanels.annotations.Fullscre
|
||||
import app.revanced.patches.youtube.layout.fullscreenpanels.fingerprints.FullscreenViewAdderFingerprint
|
||||
import app.revanced.patches.youtube.layout.fullscreenpanels.fingerprints.FullscreenViewAdderParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
|
||||
|
||||
@Patch
|
||||
@Name("disable-fullscreen-panels")
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
|
||||
@Description("Disables video description and comments panel in fullscreen view.")
|
||||
@FullscreenPanelsCompatibility
|
||||
@Version("0.0.1")
|
||||
@ -30,6 +33,16 @@ class FullscreenPanelsRemoverPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_fullscreen_panels_enabled",
|
||||
StringResource("revanced_fullscreen_panels_enabled_title", "Show fullscreen panels"),
|
||||
false,
|
||||
StringResource("revanced_fullscreen_panels_summary_on", "Fullscreen panels are shown"),
|
||||
StringResource("revanced_fullscreen_panels_summary_off", "Fullscreen panels are hidden")
|
||||
)
|
||||
)
|
||||
|
||||
val parentResult = FullscreenViewAdderParentFingerprint.result!!
|
||||
FullscreenViewAdderFingerprint.resolve(data, parentResult.method, parentResult.classDef)
|
||||
val result = FullscreenViewAdderParentFingerprint.result
|
||||
|
@ -13,10 +13,13 @@ import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.layout.oldqualitylayout.annotations.OldQualityLayoutCompatibility
|
||||
import app.revanced.patches.youtube.layout.oldqualitylayout.fingerprints.QualityMenuViewInflateFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
|
||||
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
|
||||
@Patch
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
|
||||
@Name("old-quality-layout")
|
||||
@Description("Enables the original quality flyout menu.")
|
||||
@OldQualityLayoutCompatibility
|
||||
@ -25,6 +28,16 @@ class OldQualityLayoutPatch : BytecodePatch(
|
||||
listOf(QualityMenuViewInflateFingerprint)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_use_old_style_quality_settings",
|
||||
StringResource("revanced_old_style_quality_settings_enabled_title", "Use old quality layout"),
|
||||
true,
|
||||
StringResource("revanced_old_style_quality_settings_summary_on", "Old quality settings are shown"),
|
||||
StringResource("revanced_old_style_quality_settings_summary_off", "New quality settings are shown")
|
||||
)
|
||||
)
|
||||
|
||||
val inflateFingerprintResult = QualityMenuViewInflateFingerprint.result!!
|
||||
val method = inflateFingerprintResult.mutableMethod
|
||||
val instructions = method.implementation!!.instructions
|
||||
|
@ -7,13 +7,18 @@ import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.layout.reels.annotations.HideReelsCompatibility
|
||||
import app.revanced.patches.youtube.layout.reels.fingerprints.HideReelsFingerprint
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
|
||||
|
||||
//@Patch TODO: this is currently in the general-bytecode-ads patch due to the integrations having a preference for including reels or not. Move it here.
|
||||
@Name("hide-reels")
|
||||
@Description("Hides reels on the home page.")
|
||||
@DependsOn([SettingsPatch::class])
|
||||
@HideReelsCompatibility
|
||||
@Version("0.0.1")
|
||||
class HideReelsPatch : BytecodePatch(
|
||||
@ -22,6 +27,16 @@ class HideReelsPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_reel_button_enabled",
|
||||
StringResource("revanced_reel_button_enabled_title", "Show reels button"),
|
||||
false,
|
||||
StringResource("revanced_reel_button_summary_on", "Reels button is shown"),
|
||||
StringResource("revanced_reel_button_summary_off", "Reels button is hidden")
|
||||
)
|
||||
)
|
||||
|
||||
val result = HideReelsFingerprint.result!!
|
||||
|
||||
// HideReel will hide the reel view before it is being used,
|
||||
|
@ -12,15 +12,16 @@ import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.TextComponentSpecParentFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.DislikeFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.LikeFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.RemoveLikeFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.TextComponentSpecParentFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.resource.patch.ReturnYouTubeDislikeResourcePatch
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.videoid.patch.VideoIdPatch
|
||||
|
||||
@Patch
|
||||
@DependsOn([IntegrationsPatch::class, VideoIdPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, VideoIdPatch::class, ReturnYouTubeDislikeResourcePatch::class])
|
||||
@Name("return-youtube-dislike")
|
||||
@Description("Shows the dislike count of videos using the Return YouTube Dislike API.")
|
||||
@ReturnYouTubeDislikeCompatibility
|
||||
@ -57,9 +58,9 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
|
||||
|
||||
val parentResult = TextComponentSpecParentFingerprint.result!!
|
||||
val createComponentMethod = parentResult.mutableClass.methods.find { method ->
|
||||
method.parameters.size >= 19 && method.parameterTypes.takeLast(4)
|
||||
.all { param -> param == "Ljava/util/concurrent/atomic/AtomicReference;" }
|
||||
}
|
||||
method.parameters.size >= 19 && method.parameterTypes.takeLast(4)
|
||||
.all { param -> param == "Ljava/util/concurrent/atomic/AtomicReference;" }
|
||||
}
|
||||
?: return PatchResultError("TextComponentSpec.createComponent not found")
|
||||
|
||||
val conversionContextParam = 5
|
||||
|
@ -0,0 +1,47 @@
|
||||
package app.revanced.patches.youtube.layout.returnyoutubedislike.resource.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.ResourceData
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility
|
||||
import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.Preference
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.util.resources.ResourceUtils.iterateXmlNodeChildren
|
||||
|
||||
@DependsOn([FixLocaleConfigErrorPatch::class, SettingsPatch::class])
|
||||
@Name("return-youtube-dislike-resource-patch")
|
||||
@Description("Adds the preferences for Return YouTube Dislike.")
|
||||
@ReturnYouTubeDislikeCompatibility
|
||||
@Version("0.0.1")
|
||||
class ReturnYouTubeDislikeResourcePatch : ResourcePatch() {
|
||||
override fun execute(data: ResourceData): PatchResult {
|
||||
val youtubePackage = "com.google.android.youtube"
|
||||
SettingsPatch.addPreference(
|
||||
Preference(
|
||||
StringResource("revanced_ryd_settings_title", "Return YouTube Dislike"),
|
||||
Preference.Intent(
|
||||
youtubePackage,
|
||||
"ryd_settings",
|
||||
"com.google.android.libraries.social.licenses.LicenseActivity"
|
||||
),
|
||||
StringResource("revanced_ryd_settings_summary", "Settings for Return YouTube Dislike"),
|
||||
)
|
||||
)
|
||||
// merge strings
|
||||
data.iterateXmlNodeChildren("returnyoutubedislike/host/values/strings.xml", "resources") {
|
||||
// TODO: figure out why this is needed
|
||||
if (!it.hasAttributes()) return@iterateXmlNodeChildren
|
||||
val attributes = it.attributes
|
||||
SettingsPatch.addString(attributes.getNamedItem("name")!!.nodeValue!!, it.textContent!!)
|
||||
}
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
@ -14,11 +14,14 @@ import app.revanced.patches.youtube.layout.shorts.button.annotations.ShortsButto
|
||||
import app.revanced.patches.youtube.layout.shorts.button.fingerprints.PivotBarButtonTabEnumFingerprint
|
||||
import app.revanced.patches.youtube.layout.shorts.button.fingerprints.PivotBarButtonsViewFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
@Patch
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
|
||||
@Name("hide-shorts-button")
|
||||
@Description("Hides the shorts button on the navigation bar.")
|
||||
@ShortsButtonCompatibility
|
||||
@ -29,6 +32,16 @@ class ShortsButtonRemoverPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_shorts_button_enabled",
|
||||
StringResource("revanced_shorts_button_enabled_title", "Show shorts button"),
|
||||
false,
|
||||
StringResource("revanced_shorts_button_summary_on", "Shorts button is shown"),
|
||||
StringResource("revanced_shorts_button_summary_off", "Shorts button is hidden")
|
||||
)
|
||||
)
|
||||
|
||||
val tabEnumResult = PivotBarButtonTabEnumFingerprint.result!!
|
||||
val tabEnumImplementation = tabEnumResult.mutableMethod.implementation!!
|
||||
val scanResultEndIndex = tabEnumResult.patternScanResult!!.endIndex
|
||||
|
@ -9,96 +9,112 @@ import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
|
||||
import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.Preference
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.util.resources.ResourceUtils
|
||||
import app.revanced.util.resources.ResourceUtils.copyResources
|
||||
import app.revanced.util.resources.ResourceUtils.copyXmlNode
|
||||
import java.nio.file.Files
|
||||
import app.revanced.util.resources.ResourceUtils.iterateXmlNodeChildren
|
||||
|
||||
@Name("sponsorblock-resource-patch")
|
||||
@SponsorBlockCompatibility
|
||||
@DependsOn([FixLocaleConfigErrorPatch::class])
|
||||
@DependsOn([FixLocaleConfigErrorPatch::class, SettingsPatch::class])
|
||||
@Version("0.0.1")
|
||||
class SponsorBlockResourcePatch : ResourcePatch() {
|
||||
override fun execute(data: ResourceData): PatchResult {
|
||||
val youtubePackage = "com.google.android.youtube"
|
||||
SettingsPatch.addPreference(
|
||||
Preference(
|
||||
StringResource("sb_settings", "SponsorBlock"),
|
||||
Preference.Intent(
|
||||
youtubePackage,
|
||||
"sponsorblock_settings",
|
||||
"com.google.android.libraries.social.licenses.LicenseActivity"
|
||||
),
|
||||
StringResource("revanced_sponsorblock_settings_summary", "SponsorBlock related settings"),
|
||||
)
|
||||
)
|
||||
val classLoader = this.javaClass.classLoader
|
||||
|
||||
/*
|
||||
merge SponsorBlock strings to main strings
|
||||
*/
|
||||
val stringsResourcePath = "values/strings.xml"
|
||||
val stringsResourceInputStream = classLoader.getResourceAsStream("sponsorblock/$stringsResourcePath")!!
|
||||
data.iterateXmlNodeChildren("sponsorblock/host/values/strings.xml", "resources") {
|
||||
// TODO: figure out why this is needed
|
||||
if (!it.hasAttributes()) return@iterateXmlNodeChildren
|
||||
|
||||
// copy nodes from the resources node to the real resource node
|
||||
"resources".copyXmlNode(
|
||||
data.xmlEditor[stringsResourceInputStream],
|
||||
data.xmlEditor["res/$stringsResourcePath"]
|
||||
).close() // close afterwards
|
||||
val attributes = it.attributes
|
||||
val key = attributes.getNamedItem("name")!!.nodeValue!!
|
||||
val value = it.textContent!!
|
||||
|
||||
// all strings of SponsorBlock which have this attribute have the attribute value false,
|
||||
// hence a null check suffices
|
||||
val formatted = attributes.getNamedItem("formatted") == null
|
||||
|
||||
SettingsPatch.addString(key, value, formatted)
|
||||
}
|
||||
|
||||
/*
|
||||
merge SponsorBlock drawables to main drawables
|
||||
*/
|
||||
val drawables = "drawable" to arrayOf(
|
||||
"ic_sb_adjust",
|
||||
"ic_sb_compare",
|
||||
"ic_sb_edit",
|
||||
"ic_sb_logo",
|
||||
"ic_sb_publish",
|
||||
"ic_sb_voting"
|
||||
)
|
||||
|
||||
val layouts = "layout" to arrayOf(
|
||||
"inline_sponsor_overlay", "new_segment", "skip_sponsor_button"
|
||||
)
|
||||
|
||||
// collect resources
|
||||
val xmlResources = arrayOf(drawables, layouts)
|
||||
|
||||
// write resources
|
||||
xmlResources.forEach { (path, resourceNames) ->
|
||||
resourceNames.forEach { name ->
|
||||
val relativePath = "$path/$name.xml"
|
||||
|
||||
Files.copy(
|
||||
classLoader.getResourceAsStream("sponsorblock/$relativePath")!!,
|
||||
data["res"].resolve(relativePath).toPath()
|
||||
)
|
||||
}
|
||||
arrayOf(
|
||||
ResourceUtils.ResourceGroup(
|
||||
"layout",
|
||||
"inline_sponsor_overlay.xml",
|
||||
"new_segment.xml",
|
||||
"skip_sponsor_button.xml"
|
||||
),
|
||||
ResourceUtils.ResourceGroup(
|
||||
// required resource for back button, because when the base APK is used, this resource will not exist
|
||||
"drawable",
|
||||
"ic_sb_adjust.xml",
|
||||
"ic_sb_compare.xml",
|
||||
"ic_sb_edit.xml",
|
||||
"ic_sb_logo.xml",
|
||||
"ic_sb_publish.xml",
|
||||
"ic_sb_voting.xml"
|
||||
),
|
||||
ResourceUtils.ResourceGroup(
|
||||
// required resource for back button, because when the base APK is used, this resource will not exist
|
||||
"drawable-xxxhdpi", "quantum_ic_skip_next_white_24.png"
|
||||
)
|
||||
).forEach { resourceGroup ->
|
||||
data.copyResources("sponsorblock", resourceGroup)
|
||||
}
|
||||
|
||||
/*
|
||||
merge xml nodes from the host to their real xml files
|
||||
*/
|
||||
|
||||
// collect all host resources
|
||||
val hostingXmlResources = mapOf("layout" to arrayOf("youtube_controls_layout"))
|
||||
|
||||
// copy nodes from host resources to their real xml files
|
||||
hostingXmlResources.forEach { (path, resources) ->
|
||||
resources.forEach { resource ->
|
||||
val hostingResourceStream = classLoader.getResourceAsStream("sponsorblock/host/$path/$resource.xml")!!
|
||||
val hostingResourceStream =
|
||||
classLoader.getResourceAsStream("sponsorblock/host/layout/youtube_controls_layout.xml")!!
|
||||
|
||||
val targetXmlEditor = data.xmlEditor["res/$path/$resource.xml"]
|
||||
"RelativeLayout".copyXmlNode(
|
||||
data.xmlEditor[hostingResourceStream],
|
||||
targetXmlEditor
|
||||
).also {
|
||||
val children = targetXmlEditor.file.getElementsByTagName("RelativeLayout").item(0).childNodes
|
||||
val targetXmlEditor = data.xmlEditor["res/layout/youtube_controls_layout.xml"]
|
||||
"RelativeLayout".copyXmlNode(
|
||||
data.xmlEditor[hostingResourceStream],
|
||||
targetXmlEditor
|
||||
).also {
|
||||
val children = targetXmlEditor.file.getElementsByTagName("RelativeLayout").item(0).childNodes
|
||||
|
||||
// Replace the startOf with the voting button view so that the button does not overlap
|
||||
for (i in 1 until children.length) {
|
||||
val view = children.item(i)
|
||||
// Replace the startOf with the voting button view so that the button does not overlap
|
||||
for (i in 1 until children.length) {
|
||||
val view = children.item(i)
|
||||
|
||||
// Replace the attribute for a specific node only
|
||||
if (!(view.hasAttributes() && view.attributes.getNamedItem("android:id").nodeValue.endsWith("live_chat_overlay_button"))) continue
|
||||
// Replace the attribute for a specific node only
|
||||
if (!(view.hasAttributes() && view.attributes.getNamedItem("android:id").nodeValue.endsWith("live_chat_overlay_button"))) continue
|
||||
|
||||
// voting button id from the voting button view from the youtube_controls_layout.xml host file
|
||||
val votingButtonId = "@+id/voting_button"
|
||||
// voting button id from the voting button view from the youtube_controls_layout.xml host file
|
||||
val votingButtonId = "@+id/voting_button"
|
||||
|
||||
view.attributes.getNamedItem("android:layout_toStartOf").nodeValue = votingButtonId
|
||||
view.attributes.getNamedItem("android:layout_toStartOf").nodeValue = votingButtonId
|
||||
|
||||
break
|
||||
}
|
||||
}.close() // close afterwards
|
||||
break
|
||||
}
|
||||
}
|
||||
}.close() // close afterwards
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
@ -17,9 +17,12 @@ import app.revanced.patches.youtube.layout.watermark.annotations.HideWatermarkCo
|
||||
import app.revanced.patches.youtube.layout.watermark.fingerprints.HideWatermarkParentFingerprint
|
||||
import app.revanced.patches.youtube.layout.watermark.fingerprints.HideWatermarkFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
|
||||
|
||||
@Patch
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
|
||||
@Name("hide-watermark")
|
||||
@Description("Hides creator's watermarks on videos.")
|
||||
@HideWatermarkCompatibility
|
||||
@ -30,6 +33,16 @@ class HideWatermarkPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_branding_watermark_enabled",
|
||||
StringResource("revanced_branding_watermark_enabled_title", "Show branding watermark"),
|
||||
false,
|
||||
StringResource("revanced_branding_watermark_summary_on", "Branding watermark is shown"),
|
||||
StringResource("revanced_branding_watermark_summary_off", "Branding watermark is hidden")
|
||||
)
|
||||
)
|
||||
|
||||
HideWatermarkFingerprint.resolve(data, HideWatermarkParentFingerprint.result!!.classDef)
|
||||
val result = HideWatermarkFingerprint.result
|
||||
?: return PatchResultError("Required parent method could not be found.")
|
||||
|
@ -3,10 +3,8 @@ package app.revanced.patches.youtube.layout.widesearchbar.fingerprints
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patches.youtube.layout.reels.annotations.HideReelsCompatibility
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.layout.widesearchbar.annotations.WideSearchbarCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
|
||||
@ -14,7 +12,6 @@ import org.jf.dexlib2.AccessFlags
|
||||
@MatchingMethod(
|
||||
"Lkrf;", "i"
|
||||
)
|
||||
@FuzzyPatternScanMethod(3)
|
||||
@WideSearchbarCompatibility
|
||||
@Version("0.0.1")
|
||||
|
||||
|
@ -19,9 +19,12 @@ import app.revanced.patches.youtube.layout.widesearchbar.fingerprints.WideSearch
|
||||
import app.revanced.patches.youtube.layout.widesearchbar.fingerprints.WideSearchbarTwoFingerprint
|
||||
import app.revanced.patches.youtube.layout.widesearchbar.fingerprints.WideSearchbarTwoParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
|
||||
|
||||
@Patch
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
|
||||
@Name("enable-wide-searchbar")
|
||||
@Description("Replaces the search icon with a wide search bar. This will hide the YouTube logo when active.")
|
||||
@WideSearchbarCompatibility
|
||||
@ -32,6 +35,16 @@ class WideSearchbarPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_wide_searchbar_enabled",
|
||||
StringResource("revanced_wide_searchbar_enabled_title", "Enable wide search bar"),
|
||||
false,
|
||||
StringResource("revanced_wide_searchbar_summary_on", "Wide search bar is enabled"),
|
||||
StringResource("revanced_wide_searchbar_summary_off", "Wide search bar is disabled")
|
||||
)
|
||||
)
|
||||
|
||||
WideSearchbarOneFingerprint.resolve(data, WideSearchbarOneParentFingerprint.result!!.classDef)
|
||||
WideSearchbarTwoFingerprint.resolve(data, WideSearchbarTwoParentFingerprint.result!!.classDef)
|
||||
|
||||
|
@ -17,6 +17,9 @@ import app.revanced.patches.youtube.misc.autorepeat.annotations.AutoRepeatCompat
|
||||
import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatFingerprint
|
||||
import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
|
||||
|
||||
@Patch
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@ -30,6 +33,16 @@ class AutoRepeatPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.MISC.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_pref_auto_repeat",
|
||||
StringResource("revanced_auto_repeat_enabled_title", "Enable auto-repeat"),
|
||||
true,
|
||||
StringResource("revanced_auto_repeat_summary_on", "Auto-repeat is enabled"),
|
||||
StringResource("revanced_auto_repeat_summary_off", "Auto-repeat is disabled")
|
||||
)
|
||||
)
|
||||
|
||||
//Get Result from the ParentFingerprint which is the playMethod we need to get.
|
||||
val parentResult = AutoRepeatParentFingerprint.result
|
||||
?: return PatchResultError("ParentFingerprint did not resolve.")
|
||||
|
@ -35,6 +35,8 @@ class CustomPlaybackSpeedPatch : BytecodePatch(
|
||||
) {
|
||||
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
//TODO: include setting to skip remembering the new speed
|
||||
|
||||
val arrayGenMethod = SpeedArrayGeneratorFingerprint.result?.mutableMethod!!
|
||||
val arrayGenMethodImpl = arrayGenMethod.implementation!!
|
||||
|
||||
|
@ -14,6 +14,9 @@ import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.misc.hdrbrightness.annotations.HDRBrightnessCompatibility
|
||||
import app.revanced.patches.youtube.misc.hdrbrightness.fingerprints.HDRBrightnessFingerprintXXZ
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import org.jf.dexlib2.iface.reference.FieldReference
|
||||
@ -23,13 +26,23 @@ import org.jf.dexlib2.iface.reference.FieldReference
|
||||
@Description("Makes the brightness of HDR videos follow the system default.")
|
||||
@HDRBrightnessCompatibility
|
||||
@Version("0.0.2")
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
|
||||
class HDRBrightnessPatch : BytecodePatch(
|
||||
listOf(
|
||||
HDRBrightnessFingerprintXXZ
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.MISC.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_pref_hdr_autobrightness",
|
||||
StringResource("revanced_hdr_autobrightness_enabled_title", "Enable auto HDR brightness"),
|
||||
true,
|
||||
StringResource("revanced_hdr_autobrightness_summary_on", "Auto HDR brightness is enabled"),
|
||||
StringResource("revanced_hdr_autobrightness_summary_off", "Auto HDR brightness is disabled")
|
||||
)
|
||||
)
|
||||
|
||||
val method = HDRBrightnessFingerprintXXZ.result?.mutableMethod
|
||||
?: return PatchResultError("HDRBrightnessFingerprint could not resolve the method!")
|
||||
|
||||
|
@ -28,8 +28,7 @@ class FixLocaleConfigErrorPatch : ResourcePatch() {
|
||||
// by replacing the attributes name
|
||||
val attribute = "android:localeConfig"
|
||||
applicationNode.setAttribute("localeConfig", applicationNode.getAttribute(attribute))
|
||||
applicationNode.removeAttribute("android:localeConfig")
|
||||
|
||||
applicationNode.removeAttribute(attribute)
|
||||
}
|
||||
|
||||
return PatchResultSuccess()
|
||||
|
@ -13,6 +13,9 @@ import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibi
|
||||
import app.revanced.patches.youtube.misc.microg.shared.Constants.BASE_MICROG_PACKAGE_NAME
|
||||
import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_PACKAGE_NAME
|
||||
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourcePatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.Preference
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
|
||||
@Name("microg-resource-patch")
|
||||
@DependsOn([FixLocaleConfigErrorPatch::class, SettingsResourcePatch::class])
|
||||
@ -21,25 +24,14 @@ import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourc
|
||||
@Version("0.0.1")
|
||||
class MicroGResourcePatch : ResourcePatch() {
|
||||
override fun execute(data: ResourceData): PatchResult {
|
||||
data.xmlEditor["res/xml/settings_fragment.xml"].use {
|
||||
val settingsElementIntent = it.file.createElement("intent")
|
||||
settingsElementIntent.setAttribute("android:targetPackage", "$BASE_MICROG_PACKAGE_NAME.android.gms")
|
||||
settingsElementIntent.setAttribute("android:targetClass", "org.microg.gms.ui.SettingsActivity")
|
||||
|
||||
val settingsElement = it.file.createElement("Preference")
|
||||
settingsElement.setAttribute("android:title", "@string/microg_settings")
|
||||
settingsElement.appendChild(settingsElementIntent)
|
||||
|
||||
it.file.firstChild.appendChild(settingsElement)
|
||||
}
|
||||
|
||||
val settingsFragment = data["res/xml/settings_fragment.xml"]
|
||||
settingsFragment.writeText(
|
||||
settingsFragment.readText().replace(
|
||||
"android:targetPackage=\"com.google.android.youtube",
|
||||
"android:targetPackage=\"$REVANCED_PACKAGE_NAME"
|
||||
SettingsPatch.addPreference(
|
||||
Preference(
|
||||
StringResource("microg_settings", "MicroG Settings"),
|
||||
Preference.Intent("$BASE_MICROG_PACKAGE_NAME.android.gms", "", "org.microg.gms.ui.SettingsActivity"),
|
||||
StringResource("microg_settings_summary", "Settings for MicroG"),
|
||||
)
|
||||
)
|
||||
SettingsPatch.renameIntentsTargetPackage(REVANCED_PACKAGE_NAME)
|
||||
|
||||
val manifest = data["AndroidManifest.xml"]
|
||||
manifest.writeText(
|
||||
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.layout.minimizedplayback.annotations
|
||||
package app.revanced.patches.youtube.misc.minimizedplayback.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
@ -1,11 +1,11 @@
|
||||
package app.revanced.patches.youtube.layout.minimizedplayback.fingerprints
|
||||
package app.revanced.patches.youtube.misc.minimizedplayback.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility
|
||||
import app.revanced.patches.youtube.misc.minimizedplayback.annotations.MinimizedPlaybackCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.layout.minimizedplayback.fingerprints
|
||||
package app.revanced.patches.youtube.misc.minimizedplayback.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
@ -6,7 +6,7 @@ import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patches.youtube.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility
|
||||
import app.revanced.patches.youtube.misc.minimizedplayback.annotations.MinimizedPlaybackCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.layout.minimizedplayback.fingerprints
|
||||
package app.revanced.patches.youtube.misc.minimizedplayback.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
@ -6,10 +6,9 @@ import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility
|
||||
import app.revanced.patches.youtube.misc.minimizedplayback.annotations.MinimizedPlaybackCompatibility
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||
|
||||
@Name("minimized-playback-manager-fingerprint")
|
||||
@MatchingMethod(
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.layout.minimizedplayback.patch
|
||||
package app.revanced.patches.youtube.misc.minimizedplayback.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
@ -12,11 +12,14 @@ import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.youtube.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility
|
||||
import app.revanced.patches.youtube.layout.minimizedplayback.fingerprints.MinimizedPlaybackKidsFingerprint
|
||||
import app.revanced.patches.youtube.layout.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint
|
||||
import app.revanced.patches.youtube.layout.minimizedplayback.fingerprints.MinimizedPlaybackSettingsFingerprint
|
||||
import app.revanced.patches.youtube.misc.minimizedplayback.annotations.MinimizedPlaybackCompatibility
|
||||
import app.revanced.patches.youtube.misc.minimizedplayback.fingerprints.MinimizedPlaybackKidsFingerprint
|
||||
import app.revanced.patches.youtube.misc.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint
|
||||
import app.revanced.patches.youtube.misc.minimizedplayback.fingerprints.MinimizedPlaybackSettingsFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.iface.reference.MethodReference
|
||||
|
||||
@ -24,7 +27,7 @@ import org.jf.dexlib2.iface.reference.MethodReference
|
||||
@Patch
|
||||
@Name("minimized-playback")
|
||||
@Description("Enables minimized and background playback.")
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
|
||||
@MinimizedPlaybackCompatibility
|
||||
@Version("0.0.1")
|
||||
class MinimizedPlaybackPatch : BytecodePatch(
|
||||
@ -33,6 +36,16 @@ class MinimizedPlaybackPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.MISC.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_enable_minimized_playback",
|
||||
StringResource("revanced_minimized_playback_enabled_title", "Enable minimized playback"),
|
||||
true,
|
||||
StringResource("revanced_minimized_playback_summary_on", "Minimized playback is enabled"),
|
||||
StringResource("revanced_minimized_playback_summary_off", "Minimized playback is disabled")
|
||||
)
|
||||
)
|
||||
|
||||
// Instead of removing all instructions like Vanced,
|
||||
// we return the method at the beginning instead
|
||||
MinimizedPlaybackManagerFingerprint.result!!.mutableMethod.addInstructions(
|
@ -33,6 +33,8 @@ class RememberVideoQualityPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
//TODO: include setting to skip remembering the new quality
|
||||
|
||||
val setterMethod = VideoQualitySetterFingerprint.result!!
|
||||
|
||||
VideoUserQualityChangeFingerprint.resolve(data, setterMethod.classDef)
|
||||
|
@ -4,7 +4,7 @@ import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility
|
||||
import app.revanced.patches.youtube.misc.settings.annotations.SettingsCompatibility
|
||||
|
||||
// TODO: This is more of a class fingerprint than a method fingerprint.
|
||||
// Convert to a class fingerprint whenever possible.
|
||||
@ -12,7 +12,7 @@ import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.Retu
|
||||
@MatchingMethod(
|
||||
"Lcom/google/android/libraries/social/licenses/LicenseActivity;", "onCreate"
|
||||
)
|
||||
@ReturnYouTubeDislikeCompatibility
|
||||
@SettingsCompatibility
|
||||
@Version("0.0.1")
|
||||
object LicenseActivityFingerprint : MethodFingerprint(
|
||||
null,
|
||||
|
@ -2,10 +2,9 @@ package app.revanced.patches.youtube.misc.settings.bytecode.fingerprints
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility
|
||||
import app.revanced.patches.youtube.misc.settings.annotations.SettingsCompatibility
|
||||
|
||||
// TODO: This is more of a class fingerprint than a method fingerprint.
|
||||
// Convert to a class fingerprint whenever possible.
|
||||
@ -13,7 +12,7 @@ import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.Retu
|
||||
@MatchingMethod(
|
||||
"Lapp/revanced/integrations/settingsmenu/ReVancedSettingActivity;", "initializeSettings"
|
||||
)
|
||||
@ReturnYouTubeDislikeCompatibility
|
||||
@SettingsCompatibility
|
||||
@Version("0.0.1")
|
||||
object ReVancedSettingsActivityFingerprint : MethodFingerprint(
|
||||
null,
|
||||
|
@ -4,7 +4,7 @@ import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility
|
||||
import app.revanced.patches.youtube.misc.settings.annotations.SettingsCompatibility
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||
@ -13,7 +13,7 @@ import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||
@MatchingMethod(
|
||||
"Lfyq;", "a"
|
||||
)
|
||||
@ReturnYouTubeDislikeCompatibility
|
||||
@SettingsCompatibility
|
||||
@Version("0.0.1")
|
||||
object ThemeSetterFingerprint : MethodFingerprint(
|
||||
"L",
|
||||
|
@ -18,14 +18,20 @@ import app.revanced.patches.youtube.misc.settings.annotations.SettingsCompatibil
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.LicenseActivityFingerprint
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.ReVancedSettingsActivityFingerprint
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.ThemeSetterFingerprint
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.BasePreference
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.ArrayResource
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.Preference
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourcePatch
|
||||
import org.jf.dexlib2.util.MethodUtil
|
||||
import java.io.Closeable
|
||||
|
||||
@Patch
|
||||
@DependsOn(
|
||||
[
|
||||
IntegrationsPatch::class,
|
||||
SettingsResourcePatch::class,
|
||||
ResourceIdMappingProviderResourcePatch::class
|
||||
]
|
||||
)
|
||||
@Name("settings")
|
||||
@ -34,7 +40,7 @@ import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourc
|
||||
@Version("0.0.1")
|
||||
class SettingsPatch : BytecodePatch(
|
||||
listOf(LicenseActivityFingerprint, ReVancedSettingsActivityFingerprint, ThemeSetterFingerprint)
|
||||
) {
|
||||
), Closeable {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
val licenseActivityResult = LicenseActivityFingerprint.result!!
|
||||
val settingsResult = ReVancedSettingsActivityFingerprint.result!!
|
||||
@ -65,7 +71,7 @@ class SettingsPatch : BytecodePatch(
|
||||
)
|
||||
}
|
||||
|
||||
// add the setTheme call to the onCreate method to not affect the offsets.
|
||||
// add the setTheme call to the onCreate method to not affect the offsets
|
||||
onCreate.addInstructions(
|
||||
1,
|
||||
"""
|
||||
@ -74,18 +80,76 @@ class SettingsPatch : BytecodePatch(
|
||||
"""
|
||||
)
|
||||
|
||||
// add the initializeSettings call to the onCreate method.
|
||||
// add the initializeSettings call to the onCreate method
|
||||
onCreate.addInstruction(
|
||||
0,
|
||||
"invoke-static { p0 }, ${settingsClass.type}->$setThemeMethodName(${licenseActivityClass.type})V"
|
||||
)
|
||||
|
||||
// get rid of, now, useless overridden methods
|
||||
licenseActivityResult.mutableClass.methods.removeIf { it.name != "onCreate" && !MethodUtil.isConstructor(it) }
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
internal companion object {
|
||||
val appearanceStringId = ResourceIdMappingProviderResourcePatch.resourceMappings.find {
|
||||
// TODO: hide this somehow
|
||||
var appearanceStringId: Long = ResourceIdMappingProviderResourcePatch.resourceMappings.find {
|
||||
it.type == "string" && it.name == "app_theme_appearance_dark"
|
||||
}!!.id
|
||||
|
||||
fun addString(identifier: String, value: String, formatted: Boolean = true) =
|
||||
SettingsResourcePatch.addString(identifier, value, formatted)
|
||||
|
||||
fun addPreferenceScreen(preferenceScreen: app.revanced.patches.youtube.misc.settings.framework.components.impl.PreferenceScreen) =
|
||||
SettingsResourcePatch.addPreferenceScreen(preferenceScreen)
|
||||
|
||||
fun addPreference(preference: Preference) =
|
||||
SettingsResourcePatch.addPreference(preference)
|
||||
|
||||
fun addArray(arrayResource: ArrayResource) =
|
||||
SettingsResourcePatch.addArray(arrayResource)
|
||||
|
||||
fun renameIntentsTargetPackage(newPackage: String) {
|
||||
SettingsResourcePatch.overrideIntentsTargetPackage = newPackage
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Preference screens patches should add their settings to.
|
||||
*/
|
||||
internal enum class PreferenceScreen(
|
||||
private val key: String,
|
||||
private val title: String,
|
||||
private val summary: String? = null,
|
||||
private val preferences: MutableList<BasePreference> = mutableListOf()
|
||||
) : Closeable {
|
||||
ADS("ads", "Ads", "Ad related settings"),
|
||||
INTERACTIONS("interactions", "Interaction", "Settings related to interactions"),
|
||||
LAYOUT("layout", "Layout", "Settings related to the layout"),
|
||||
MISC("misc", "Miscellaneous", "Miscellaneous patches");
|
||||
|
||||
override fun close() {
|
||||
if (preferences.size == 0) return
|
||||
|
||||
addPreferenceScreen(
|
||||
PreferenceScreen(
|
||||
key,
|
||||
StringResource("${key}_title", title),
|
||||
preferences,
|
||||
summary?.let { summary ->
|
||||
StringResource("${key}_summary", summary)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Add preferences to the preference screen.
|
||||
*/
|
||||
fun addPreferences(vararg preferences: BasePreference) = this.preferences.addAll(preferences)
|
||||
}
|
||||
|
||||
override fun close() = PreferenceScreen.values().forEach(PreferenceScreen::close)
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package app.revanced.patches.youtube.misc.settings.framework.components
|
||||
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
|
||||
/**
|
||||
* Base preference class for all preferences.
|
||||
*
|
||||
* @param key The key of the preference.
|
||||
* @param title The title of the preference.
|
||||
*/
|
||||
internal abstract class BasePreference(
|
||||
override val key: String,
|
||||
override val title: StringResource,
|
||||
) : IPreference
|
@ -0,0 +1,23 @@
|
||||
package app.revanced.patches.youtube.misc.settings.framework.components
|
||||
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
|
||||
/**
|
||||
* Preference
|
||||
*/
|
||||
internal interface IPreference {
|
||||
/**
|
||||
* Key of the preference.
|
||||
*/
|
||||
val key: String
|
||||
|
||||
/**
|
||||
* Title of the preference.
|
||||
*/
|
||||
val title: StringResource
|
||||
|
||||
/**
|
||||
* Tag name of the preference.
|
||||
*/
|
||||
val tag: String
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package app.revanced.patches.youtube.misc.settings.framework.components.impl
|
||||
|
||||
/**
|
||||
* Represents an array resource.
|
||||
*
|
||||
* @param name The name of the array resource.
|
||||
* @param items The items of the array resource.
|
||||
*/
|
||||
internal data class ArrayResource(val name: String, val items: List<StringResource>)
|
@ -0,0 +1,6 @@
|
||||
package app.revanced.patches.youtube.misc.settings.framework.components.impl
|
||||
|
||||
enum class InputType(val type: String) {
|
||||
STRING("text"),
|
||||
NUMBER("number"),
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package app.revanced.patches.youtube.misc.settings.framework.components.impl
|
||||
|
||||
/**
|
||||
* A Preference object.
|
||||
*
|
||||
* @param title The title of the preference.
|
||||
* @param intent The intent of the preference.
|
||||
* @param summary The summary of the text preference.
|
||||
*/
|
||||
internal class Preference(
|
||||
val title: StringResource,
|
||||
val intent: Intent,
|
||||
val summary: StringResource? = null
|
||||
) {
|
||||
val tag: String = "Preference"
|
||||
|
||||
data class Intent(val targetPackage: String, val data: String, val targetClass: String)
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package app.revanced.patches.youtube.misc.settings.framework.components.impl
|
||||
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.BasePreference
|
||||
|
||||
/**
|
||||
* Preference screen.
|
||||
*
|
||||
* @param key The key of the preference.
|
||||
* @param title The title of the preference.
|
||||
* @param preferences Child preferences of this screen.
|
||||
* @param summary The summary of the text preference.
|
||||
*/
|
||||
internal open class PreferenceScreen(
|
||||
key: String,
|
||||
title: StringResource,
|
||||
val preferences: List<BasePreference>,
|
||||
var summary: StringResource? = null
|
||||
) : BasePreference(key, title) {
|
||||
override val tag: String = "PreferenceScreen"
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package app.revanced.patches.youtube.misc.settings.framework.components.impl
|
||||
|
||||
/**
|
||||
* Represents a string value in the strings.xml file
|
||||
*
|
||||
* @param name The name of the string
|
||||
* @param value The value of the string
|
||||
* @param formatted If the string is formatted. If false, the attribute will be set
|
||||
*/
|
||||
internal data class StringResource(val name: String, val value: String, val formatted: Boolean = true)
|
@ -0,0 +1,21 @@
|
||||
package app.revanced.patches.youtube.misc.settings.framework.components.impl
|
||||
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.BasePreference
|
||||
|
||||
/**
|
||||
* Switch preference.
|
||||
*
|
||||
* @param key The key of the switch.
|
||||
* @param title The title of the switch.
|
||||
* @param default The default value of the switch.
|
||||
* @param summaryOn The summary to show when the preference is enabled.
|
||||
* @param summaryOff The summary to show when the preference is disabled.
|
||||
*/
|
||||
internal class SwitchPreference(
|
||||
key: String, title: StringResource,
|
||||
val default: Boolean = false,
|
||||
var summaryOn: StringResource? = null,
|
||||
var summaryOff: StringResource? = null
|
||||
) : BasePreference(key, title) {
|
||||
override val tag: String = "SwitchPreference"
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package app.revanced.patches.youtube.misc.settings.framework.components.impl
|
||||
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.BasePreference
|
||||
|
||||
/**
|
||||
* Text preference.
|
||||
*
|
||||
* @param key The key of the text preference.
|
||||
* @param title The title of the text preference.
|
||||
* @param inputType The input type of the text preference.
|
||||
* @param default The default value of the text preference.
|
||||
* @param summary The summary of the text preference.
|
||||
*/
|
||||
internal class TextPreference(
|
||||
key: String,
|
||||
title: StringResource,
|
||||
var inputType: InputType = InputType.STRING,
|
||||
var default: String? = null,
|
||||
var summary: StringResource? = null
|
||||
) : BasePreference(key, title) {
|
||||
override val tag: String = "EditTextPreference"
|
||||
}
|
@ -2,71 +2,290 @@ package app.revanced.patches.youtube.misc.settings.resource.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.impl.DomFileEditor
|
||||
import app.revanced.patcher.data.impl.ResourceData
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
||||
import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch
|
||||
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
|
||||
import app.revanced.patches.youtube.misc.settings.annotations.SettingsCompatibility
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.BasePreference
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.*
|
||||
import app.revanced.util.resources.ResourceUtils
|
||||
import app.revanced.util.resources.ResourceUtils.copyResources
|
||||
import app.revanced.util.resources.ResourceUtils.copyXmlNode
|
||||
import org.w3c.dom.Element
|
||||
import org.w3c.dom.Node
|
||||
import java.io.Closeable
|
||||
|
||||
@Name("settings-resource-patch")
|
||||
@SettingsCompatibility
|
||||
@DependsOn([FixLocaleConfigErrorPatch::class])
|
||||
@DependsOn([FixLocaleConfigErrorPatch::class, ResourceIdMappingProviderResourcePatch::class])
|
||||
@Version("0.0.1")
|
||||
class SettingsResourcePatch : ResourcePatch() {
|
||||
class SettingsResourcePatch : ResourcePatch(), Closeable {
|
||||
|
||||
override fun execute(data: ResourceData): PatchResult {
|
||||
/*
|
||||
* Copy strings
|
||||
* create missing directory for the resources
|
||||
*/
|
||||
|
||||
data.copyXmlNode("settings/host", "values/strings.xml", "resources")
|
||||
data["res/drawable-ldrtl-xxxhdpi"].mkdirs()
|
||||
|
||||
/*
|
||||
* Copy arrays
|
||||
*/
|
||||
|
||||
data.copyXmlNode("settings/host", "values/arrays.xml", "resources")
|
||||
|
||||
/*
|
||||
* Copy preference fragments
|
||||
*/
|
||||
|
||||
data.copyXmlNode("settings/host", "xml/settings_fragment.xml", "PreferenceScreen")
|
||||
|
||||
/*
|
||||
* Copy layout resources
|
||||
* copy layout resources
|
||||
*/
|
||||
arrayOf(
|
||||
ResourceUtils.ResourceGroup(
|
||||
"layout",
|
||||
"xsettings_toolbar.xml",
|
||||
"xsettings_with_toolbar.xml",
|
||||
"xsettings_with_toolbar_layout.xml"
|
||||
),
|
||||
ResourceUtils.ResourceGroup(
|
||||
"xml",
|
||||
"revanced_prefs.xml"
|
||||
"revanced_settings_toolbar.xml",
|
||||
"revanced_settings_with_toolbar.xml",
|
||||
"revanced_settings_with_toolbar_layout.xml"
|
||||
), ResourceUtils.ResourceGroup(
|
||||
"xml", "revanced_prefs.xml" // template for new preferences
|
||||
), ResourceUtils.ResourceGroup(
|
||||
// required resource for back button, because when the base APK is used, this resource will not exist
|
||||
"drawable-xxxhdpi", "quantum_ic_arrow_back_white_24.png"
|
||||
), ResourceUtils.ResourceGroup(
|
||||
// required resource for back button, because when the base APK is used, this resource will not exist
|
||||
"drawable-ldrtl-xxxhdpi", "quantum_ic_arrow_back_white_24.png"
|
||||
)
|
||||
).forEach { resourceGroup ->
|
||||
data.copyResources("settings", resourceGroup)
|
||||
}
|
||||
|
||||
data.xmlEditor["AndroidManifest.xml"].use {
|
||||
val manifestNode = it
|
||||
.file
|
||||
.getElementsByTagName("manifest")
|
||||
.item(0) as Element
|
||||
|
||||
val element = it.file.createElement("uses-permission")
|
||||
element.setAttribute("android:name", "android.permission.SCHEDULE_EXACT_ALARM")
|
||||
manifestNode.appendChild(element)
|
||||
data.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||
editor.file.getElementsByTagName("manifest").item(0).also {
|
||||
it.appendChild(it.ownerDocument.createElement("uses-permission").also { element ->
|
||||
element.setAttribute("android:name", "android.permission.SCHEDULE_EXACT_ALARM")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
revancedPreferencesEditor = data.xmlEditor["res/xml/revanced_prefs.xml"]
|
||||
preferencesEditor = data.xmlEditor["res/xml/settings_fragment.xml"]
|
||||
|
||||
stringsEditor = data.xmlEditor["res/values/strings.xml"]
|
||||
arraysEditor = data.xmlEditor["res/values/arrays.xml"]
|
||||
|
||||
// Add the ReVanced settings to the YouTube settings
|
||||
val youtubePackage = "com.google.android.youtube"
|
||||
SettingsPatch.addPreference(
|
||||
Preference(
|
||||
StringResource("revanced_settings", "ReVanced"),
|
||||
Preference.Intent(
|
||||
youtubePackage, "revanced_settings", "com.google.android.libraries.social.licenses.LicenseActivity"
|
||||
),
|
||||
StringResource("revanced_settings_summary", "ReVanced specific settings"),
|
||||
)
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
|
||||
internal companion object {
|
||||
// if this is not null, all intents will be renamed to this
|
||||
var overrideIntentsTargetPackage: String? = null
|
||||
|
||||
private var revancedPreferenceNode: Node? = null
|
||||
private var preferencesNode: Node? = null
|
||||
|
||||
private var stringsNode: Node? = null
|
||||
private var arraysNode: Node? = null
|
||||
|
||||
private var strings = mutableListOf<StringResource>()
|
||||
|
||||
private var revancedPreferencesEditor: DomFileEditor? = null
|
||||
set(value) {
|
||||
field = value
|
||||
revancedPreferenceNode = value.getNode("PreferenceScreen")
|
||||
}
|
||||
private var preferencesEditor: DomFileEditor? = null
|
||||
set(value) {
|
||||
field = value
|
||||
preferencesNode = value.getNode("PreferenceScreen")
|
||||
}
|
||||
|
||||
private var stringsEditor: DomFileEditor? = null
|
||||
set(value) {
|
||||
field = value
|
||||
stringsNode = value.getNode("resources")
|
||||
}
|
||||
private var arraysEditor: DomFileEditor? = null
|
||||
set(value) {
|
||||
field = value
|
||||
arraysNode = value.getNode("resources")
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new string to the resources.
|
||||
*
|
||||
* @param identifier The key of the string.
|
||||
* @param value The value of the string.
|
||||
* @throws IllegalArgumentException if the string already exists.
|
||||
*/
|
||||
fun addString(identifier: String, value: String, formatted: Boolean) =
|
||||
StringResource(identifier, value, formatted).include()
|
||||
|
||||
/**
|
||||
* Add an array to the resources.
|
||||
*
|
||||
* @param arrayResource The array resource to add.
|
||||
*/
|
||||
fun addArray(arrayResource: ArrayResource) {
|
||||
arraysNode!!.appendChild(arraysNode!!.ownerDocument.createElement("string-array").also { arrayNode ->
|
||||
arrayResource.items.forEach { item ->
|
||||
item.include()
|
||||
|
||||
arrayNode.setAttribute("name", item.name)
|
||||
|
||||
arrayNode.appendChild(arrayNode.ownerDocument.createElement("item").also { itemNode ->
|
||||
itemNode.textContent = item.value
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a preference screen to the settings.
|
||||
*
|
||||
* @param preferenceScreen The name of the preference screen.
|
||||
*/
|
||||
fun addPreferenceScreen(preferenceScreen: PreferenceScreen) =
|
||||
revancedPreferenceNode!!.addPreference(preferenceScreen)
|
||||
|
||||
/**
|
||||
* Add a preference fragment to the preferences.
|
||||
*
|
||||
* @param preference The preference to add.
|
||||
*/
|
||||
fun addPreference(preference: Preference) {
|
||||
preferencesNode!!.appendChild(preferencesNode.createElement(preference.tag).also { preferenceNode ->
|
||||
preferenceNode.setAttribute(
|
||||
"android:title", "@string/${preference.title.also { it.include() }.name}"
|
||||
)
|
||||
preference.summary?.let { summary ->
|
||||
preferenceNode.setAttribute("android:summary", "@string/${summary.also { it.include() }.name}")
|
||||
}
|
||||
|
||||
preferenceNode.appendChild(preferenceNode.createElement("intent").also { intentNode ->
|
||||
intentNode.setAttribute("android:targetPackage", preference.intent.targetPackage)
|
||||
intentNode.setAttribute("android:data", preference.intent.data)
|
||||
intentNode.setAttribute("android:targetClass", preference.intent.targetClass)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a preference to the settings.
|
||||
*
|
||||
* @param preference The preference to add.
|
||||
*/
|
||||
private fun Node.addPreference(preference: BasePreference) {
|
||||
// add a summary to the element
|
||||
fun Element.addSummary(summaryResource: StringResource?, summaryType: SummaryType = SummaryType.DEFAULT) =
|
||||
summaryResource?.let { summary ->
|
||||
setAttribute("android:${summaryType.type}", "@string/${summary.also { it.include() }.name}")
|
||||
}
|
||||
|
||||
fun <T> Element.addDefault(default: T) {
|
||||
default?.let {
|
||||
setAttribute(
|
||||
"android:defaultValue", when (it) {
|
||||
is Boolean -> if (it) "true" else "false"
|
||||
is String -> it
|
||||
else -> throw IllegalArgumentException("Unsupported default value type: ${it::class.java.name}")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val preferenceElement = ownerDocument.createElement(preference.tag)
|
||||
preferenceElement.setAttribute("android:key", preference.key)
|
||||
preferenceElement.setAttribute("android:title", "@string/${preference.title.also { it.include() }.name}")
|
||||
|
||||
when (preference) {
|
||||
is PreferenceScreen -> {
|
||||
for (childPreference in preference.preferences) preferenceElement.addPreference(childPreference)
|
||||
preferenceElement.addSummary(preference.summary)
|
||||
}
|
||||
is SwitchPreference -> {
|
||||
preferenceElement.addDefault(preference.default)
|
||||
preferenceElement.addSummary(preference.summaryOn, SummaryType.ON)
|
||||
preferenceElement.addSummary(preference.summaryOff, SummaryType.OFF)
|
||||
}
|
||||
is TextPreference -> {
|
||||
preferenceElement.setAttribute("android:inputType", preference.inputType.type)
|
||||
preferenceElement.addDefault(preference.default)
|
||||
preferenceElement.addSummary(preference.summary)
|
||||
}
|
||||
}
|
||||
|
||||
appendChild(preferenceElement)
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new string to the resources.
|
||||
*
|
||||
* @throws IllegalArgumentException if the string already exists.
|
||||
*/
|
||||
private fun StringResource.include() {
|
||||
if (strings.any { it.name == name }) return
|
||||
strings.add(this)
|
||||
}
|
||||
|
||||
private fun DomFileEditor?.getNode(tagName: String) = this!!.file.getElementsByTagName(tagName).item(0)
|
||||
|
||||
private fun Node?.createElement(tagName: String) = this!!.ownerDocument.createElement(tagName)
|
||||
|
||||
private enum class SummaryType(val type: String) {
|
||||
DEFAULT("summary"), ON("summaryOn"), OFF("summaryOff")
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
// merge all strings, skip duplicates
|
||||
strings.forEach { stringResource ->
|
||||
stringsNode!!.appendChild(stringsNode!!.ownerDocument.createElement("string").also { stringElement ->
|
||||
stringElement.setAttribute("name", stringResource.name)
|
||||
|
||||
// if the string is un-formatted, explicitly add the formatted attribute
|
||||
if (!stringResource.formatted) stringElement.setAttribute("formatted", "false")
|
||||
|
||||
stringElement.textContent = stringResource.value
|
||||
})
|
||||
}
|
||||
|
||||
// rename the intent package names if it was set
|
||||
overrideIntentsTargetPackage?.let { packageName ->
|
||||
val preferences = preferencesEditor!!.getNode("PreferenceScreen").childNodes
|
||||
for (i in 1 until preferences.length) {
|
||||
val preferenceNode = preferences.item(i)
|
||||
// preferences have a child node with the intent tag, skip over every other node
|
||||
if (preferenceNode.childNodes.length == 0) continue
|
||||
|
||||
val intentNode = preferenceNode.firstChild
|
||||
|
||||
// if the node doesn't have a target package attribute, skip it
|
||||
val targetPackageAttribute = intentNode.attributes.getNamedItem("android:targetPackage") ?: continue
|
||||
|
||||
// do not replace intent target package if the package name is not from YouTube
|
||||
val youtubePackage = "com.google.android.youtube"
|
||||
if (targetPackageAttribute.nodeValue != youtubePackage) continue
|
||||
|
||||
// replace the target package name
|
||||
intentNode.attributes.setNamedItem(preferenceNode.ownerDocument.createAttribute("android:targetPackage")
|
||||
.also { attribute ->
|
||||
attribute.value = packageName
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
revancedPreferencesEditor?.close()
|
||||
preferencesEditor?.close()
|
||||
stringsEditor?.close()
|
||||
arraysEditor?.close()
|
||||
}
|
||||
}
|
@ -7,8 +7,14 @@ import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.InputType
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
|
||||
import app.revanced.patches.youtube.misc.settings.framework.components.impl.TextPreference
|
||||
import app.revanced.patches.youtube.misc.videobuffer.annotations.CustomVideoBufferCompatibility
|
||||
import app.revanced.patches.youtube.misc.videobuffer.fingerprints.MaxBufferFingerprint
|
||||
import app.revanced.patches.youtube.misc.videobuffer.fingerprints.PlaybackBufferFingerprint
|
||||
@ -18,6 +24,7 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
@Patch
|
||||
@Name("custom-video-buffer")
|
||||
@Description("Lets you change the buffers of videos.")
|
||||
@DependsOn([SettingsPatch::class])
|
||||
@CustomVideoBufferCompatibility
|
||||
@Version("0.0.1")
|
||||
class CustomVideoBufferPatch : BytecodePatch(
|
||||
@ -26,9 +33,52 @@ class CustomVideoBufferPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
override fun execute(data: BytecodeData): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.MISC.addPreferences(
|
||||
PreferenceScreen(
|
||||
"revanced_custom_video_buffer",
|
||||
StringResource("revanced_custom_video_buffer_title", "Video buffer settings"),
|
||||
listOf(
|
||||
TextPreference(
|
||||
"revanced_pref_max_buffer_ms",
|
||||
StringResource("revanced_pref_max_buffer_ms_title", "Maximum buffer size"),
|
||||
InputType.NUMBER,
|
||||
"120000",
|
||||
StringResource(
|
||||
"revanced_pref_max_buffer_ms_summary",
|
||||
"The maximum size of a buffer for playback"
|
||||
)
|
||||
),
|
||||
TextPreference(
|
||||
"revanced_pref_buffer_for_playback_ms",
|
||||
StringResource("revanced_pref_buffer_for_playback_ms_title", "Maximum buffer for playback"),
|
||||
InputType.NUMBER,
|
||||
"2500",
|
||||
StringResource(
|
||||
"revanced_pref_buffer_for_playback_ms_summary",
|
||||
"Maximum size of a buffer for playback"
|
||||
)
|
||||
),
|
||||
TextPreference(
|
||||
"revanced_pref_buffer_for_playback_after_rebuffer_ms",
|
||||
StringResource(
|
||||
"revanced_pref_buffer_for_playback_after_rebuffer_ms_title",
|
||||
"Maximum buffer for playback after rebuffer"
|
||||
),
|
||||
InputType.NUMBER,
|
||||
"5000",
|
||||
StringResource(
|
||||
"revanced_pref_buffer_for_playback_after_rebuffer_ms_summary",
|
||||
"Maximum size of a buffer for playback after rebuffering"
|
||||
)
|
||||
)
|
||||
),
|
||||
StringResource("revanced_custom_video_buffer_summary", "Custom settings for video buffer")
|
||||
)
|
||||
)
|
||||
|
||||
execMaxBuffer()
|
||||
execPlaybackBuffer(data)
|
||||
execReBuffer(data)
|
||||
execPlaybackBuffer()
|
||||
execReBuffer()
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
@ -36,7 +86,7 @@ class CustomVideoBufferPatch : BytecodePatch(
|
||||
val result = MaxBufferFingerprint.result!!
|
||||
val method = result.mutableMethod
|
||||
val index = result.patternScanResult!!.endIndex - 1
|
||||
val register = (method.implementation!!.instructions.get(index) as OneRegisterInstruction).registerA
|
||||
val register = (method.implementation!!.instructions[index] as OneRegisterInstruction).registerA
|
||||
method.addInstructions(
|
||||
index + 1, """
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/VideoBufferPatch;->getMaxBuffer()I
|
||||
@ -45,11 +95,11 @@ class CustomVideoBufferPatch : BytecodePatch(
|
||||
)
|
||||
}
|
||||
|
||||
private fun execPlaybackBuffer(data: BytecodeData) {
|
||||
private fun execPlaybackBuffer() {
|
||||
val result = PlaybackBufferFingerprint.result!!
|
||||
val method = result.mutableMethod
|
||||
val index = result.patternScanResult!!.startIndex
|
||||
val register = (method.implementation!!.instructions.get(index) as OneRegisterInstruction).registerA
|
||||
val register = (method.implementation!!.instructions[index] as OneRegisterInstruction).registerA
|
||||
method.addInstructions(
|
||||
index + 1, """
|
||||
invoke-static {}, Lapp/revanced/integrations/patches/VideoBufferPatch;->getPlaybackBuffer()I
|
||||
@ -58,7 +108,7 @@ class CustomVideoBufferPatch : BytecodePatch(
|
||||
)
|
||||
}
|
||||
|
||||
private fun execReBuffer(data: BytecodeData) {
|
||||
private fun execReBuffer() {
|
||||
val result = ReBufferFingerprint.result!!
|
||||
val method = result.mutableMethod
|
||||
val index = result.patternScanResult!!.startIndex
|
||||
|
@ -2,7 +2,9 @@ package app.revanced.util.resources
|
||||
|
||||
import app.revanced.patcher.data.impl.DomFileEditor
|
||||
import app.revanced.patcher.data.impl.ResourceData
|
||||
import org.w3c.dom.Node
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardCopyOption
|
||||
|
||||
internal object ResourceUtils {
|
||||
/**
|
||||
@ -19,7 +21,7 @@ internal object ResourceUtils {
|
||||
val resourceFile = "${resourceGroup.resourceDirectoryName}/$resource"
|
||||
Files.copy(
|
||||
classLoader.getResourceAsStream("$sourceResourceDirectory/$resourceFile")!!,
|
||||
targetResourceDirectory.resolve(resourceFile).toPath()
|
||||
targetResourceDirectory.resolve(resourceFile).toPath(), StandardCopyOption.REPLACE_EXISTING
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -33,20 +35,17 @@ internal object ResourceUtils {
|
||||
internal class ResourceGroup(val resourceDirectoryName: String, vararg val resources: String)
|
||||
|
||||
/**
|
||||
* Copy resources from the current class loader to the resource directory.
|
||||
* @param resourceDirectory The directory of the resource.
|
||||
* @param targetResource The target resource.
|
||||
* @param elementTag The element to copy.
|
||||
* Iterate through the children of a node by its tag.
|
||||
* @param resource The xml resource.
|
||||
* @param targetTag The target xml node.
|
||||
* @param callback The callback to call when iterating over the nodes.
|
||||
*/
|
||||
internal fun ResourceData.copyXmlNode(resourceDirectory: String, targetResource: String, elementTag: String) {
|
||||
val stringsResourceInputStream = ResourceUtils.javaClass.classLoader.getResourceAsStream("$resourceDirectory/$targetResource")!!
|
||||
internal fun ResourceData.iterateXmlNodeChildren(resource: String, targetTag: String, callback: (node: Node) -> Unit) =
|
||||
xmlEditor[ResourceUtils.javaClass.classLoader.getResourceAsStream(resource)!!].use {
|
||||
val stringsNode = it.file.getElementsByTagName(targetTag).item(0).childNodes
|
||||
for (i in 1 until stringsNode.length - 1) callback(stringsNode.item(i))
|
||||
}
|
||||
|
||||
// Copy nodes from the resources node to the real resource node
|
||||
elementTag.copyXmlNode(
|
||||
this.xmlEditor[stringsResourceInputStream],
|
||||
this.xmlEditor["res/$targetResource"]
|
||||
).close()
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the specified node of the source [DomFileEditor] to the target [DomFileEditor].
|
||||
@ -54,7 +53,7 @@ internal object ResourceUtils {
|
||||
* @param target the target [DomFileEditor]-
|
||||
* @return AutoCloseable that closes the target [DomFileEditor]s.
|
||||
*/
|
||||
internal fun String.copyXmlNode(source: DomFileEditor, target: DomFileEditor): AutoCloseable {
|
||||
fun String.copyXmlNode(source: DomFileEditor, target: DomFileEditor): AutoCloseable {
|
||||
val hostNodes = source.file.getElementsByTagName(this).item(0).childNodes
|
||||
|
||||
val destinationResourceFile = target.file
|
||||
|
@ -0,0 +1,6 @@
|
||||
<resources>
|
||||
<string name="revanced_ryd_title">Enable Return YouTube Dislike</string>
|
||||
<string name="revanced_ryd_summary">Switch this on to see the dislike counts again</string>
|
||||
<string name="revanced_ryd_attribution_title">Return YouTube Dislike patch</string>
|
||||
<string name="revanced_ryd_attribution_summary">This patch uses the Return YouTube Dislike API from https://returnyoutubedislike.com. Tap to learn more</string>
|
||||
</resources>
|
Binary file not shown.
After Width: | Height: | Size: 200 B |
Binary file not shown.
After Width: | Height: | Size: 194 B |
@ -1,14 +0,0 @@
|
||||
<resources>
|
||||
<string-array name="revanced_button_location_entries">
|
||||
<item>@string/revanced_button_location_entry_none</item>
|
||||
<item>@string/revanced_button_location_entry_player</item>
|
||||
<item>@string/revanced_button_location_entry_buttoncontainer</item>
|
||||
<item>@string/revanced_button_location_entry_both</item>
|
||||
</string-array>
|
||||
<string-array name="revanced_button_location_entry_values">
|
||||
<item>NONE</item>
|
||||
<item>PLAYER</item>
|
||||
<item>BUTTON_CONTAINER</item>
|
||||
<item>BOTH</item>
|
||||
</string-array>
|
||||
</resources>
|
@ -1,227 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="revanced_auto_repeat_button_summary_off">"Doesn't show auto-repeat button in the player overlay. Use the toggle below to control auto-repeat"</string>
|
||||
<string name="revanced_auto_repeat_button_summary_on">Auto-repeat button is shown in the player overlay</string>
|
||||
<string name="revanced_auto_repeat_button_title">Auto-repeat button</string>
|
||||
<string name="revanced_auto_repeat_summary_off">Always Auto-repeat is off</string>
|
||||
<string name="revanced_auto_repeat_summary_on">Always Auto-repeat is on</string>
|
||||
<string name="revanced_auto_repeat_title">Always Auto-repeat</string>
|
||||
<string name="revanced_branding_watermark_summary_off">Video watermark is hidden</string>
|
||||
<string name="revanced_branding_watermark_summary_on">Video watermark is shown</string>
|
||||
<string name="revanced_branding_watermark_title">Video watermark</string>
|
||||
<string name="revanced_buffer_title">Buffer settings</string>
|
||||
<string name="revanced_cast_button_summary_off">Cast button is hidden</string>
|
||||
<string name="revanced_cast_button_summary_on">Cast button is shown</string>
|
||||
<string name="revanced_cast_button_title">Cast button</string>
|
||||
<string name="revanced_autoplay_button_summary_off">Autoplay button is hidden</string>
|
||||
<string name="revanced_autoplay_button_summary_on">Autoplay button is shown</string>
|
||||
<string name="revanced_autoplay_button_title">Autoplay button</string>
|
||||
<string name="revanced_codec_override_title">Codec override</string>
|
||||
<string name="revanced_debug_summary_off">Extra debug logging is disabled</string>
|
||||
<string name="revanced_debug_summary_on">Extra Debug logging is enabled</string>
|
||||
<string name="revanced_debug_title">Debug mode</string>
|
||||
<string name="revanced_discord_summary">Tap to join ReVanced on Discord</string>
|
||||
<string name="revanced_discord_title">Discord server</string>
|
||||
<string name="revanced_hdr_full_brightness_summary_on">Video brightness will follow your device\'s brightness on HDR landscape videos</string>
|
||||
<string name="revanced_hdr_full_brightness_summary_off">Video brightness is set to max on HDR landscape videos</string>
|
||||
<string name="revanced_hdr_full_brightness_title">Override HDR Video Brightness</string>
|
||||
<string name="revanced_info_cards_summary_off">Info cards are hidden</string>
|
||||
<string name="revanced_info_cards_summary_on">Info cards are shown</string>
|
||||
<string name="revanced_info_cards_title">Info cards</string>
|
||||
<string name="revanced_layout_settings_title">Layout settings</string>
|
||||
<string name="revanced_maximum_buffer_summary">"The maximum duration of media that the player will attempt to buffer (in milliseconds)
|
||||
|
||||
Default: 120000"</string>
|
||||
<string name="revanced_maximum_buffer_title">Maximum buffer</string>
|
||||
<string name="revanced_misc_title">Miscellaneous</string>
|
||||
<string name="revanced_playback_start_summary">"The duration of media that must be buffered for playback to start or resume following a user action such as seeking (in milliseconds)
|
||||
|
||||
Default: 2500"</string>
|
||||
<string name="revanced_playback_start_title">Playback start</string>
|
||||
<string name="revanced_preferred_video_speed_summary">Select preferred video speed</string>
|
||||
<string name="revanced_preferred_video_speed_title">Preferred video speed</string>
|
||||
<string name="revanced_rebuffer_summary">"The duration of media that must be buffered for playback to resume after a rebuffer (in milliseconds). A rebuffer is defined to be caused by buffer depletion rather than a user action
|
||||
|
||||
Default: 5000"</string>
|
||||
<string name="revanced_rebuffer_title">Rebuffer</string>
|
||||
<string name="revanced_suggestion_summary_off">End screens are hidden</string>
|
||||
<string name="revanced_suggestion_summary_on">End screens are shown</string>
|
||||
<string name="revanced_suggestion_title">End screens</string>
|
||||
<string name="revanced_support_summary">Support links</string>
|
||||
<string name="revanced_support_title">Support</string>
|
||||
<string name="revanced_video_settings_title">Video settings</string>
|
||||
<string name="revanced_vp9_summary">Tap to force usage of the VP9 codec</string>
|
||||
<string name="revanced_vp9_summary_off">VP9 codec not forced</string>
|
||||
<string name="revanced_vp9_summary_on">VP9 codec is enabled by default for supported devices, disable if you encounter stuttering/slowness in videos</string>
|
||||
<string name="revanced_vp9_title">VP9 codec</string>
|
||||
<string name="revanced_new_actionbar_title">Wide search bar</string>
|
||||
<string name="revanced_new_actionbar_summary_off">Search bar style is defined by the app</string>
|
||||
<string name="revanced_new_actionbar_summary_on">Forcing wide search bar</string>
|
||||
<string name="revanced_shorts_button_title">Show shorts button</string>
|
||||
<string name="revanced_shorts_button_summary_off">Shorts button is hidden</string>
|
||||
<string name="revanced_shorts_button_summary_on">Shorts button is shown</string>
|
||||
<string name="revanced_fullscreen_panels_title">Fullscreen panels</string>
|
||||
<string name="revanced_fullscreen_panels_summary_off">Fullscreen panels are hidden</string>
|
||||
<string name="revanced_fullscreen_panels_summary_on">Fullscreen panels are shown</string>
|
||||
<string name="revanced_zoom_to_fit_vertical_title">Dynamic player</string>
|
||||
<string name="revanced_zoom_to_fit_vertical_summary_off">Dynamic player is defined automatically</string>
|
||||
<string name="revanced_zoom_to_fit_vertical_summary_on">Dynamic player is forced on square and vertical videos</string>
|
||||
<string name="revanced_auto_captions_summary_off">Captions aren\'t enabled automatically at 0% volume </string>
|
||||
<string name="revanced_auto_captions_summary_on">Captions are enabled automatically at 0% volume</string>
|
||||
<string name="revanced_auto_captions_title">Auto captions</string>
|
||||
<string name="revanced_swipe_brightness_summary_off">Swipe controls for brightness are disabled</string>
|
||||
<string name="revanced_swipe_brightness_summary_on">Swipe controls for brightness are enabled</string>
|
||||
<string name="revanced_swipe_brightness_title">Swipe controls for Brightness</string>
|
||||
<string name="revanced_swipe_screen_summary">Swipe controls for Brightness and Volume</string>
|
||||
<string name="revanced_swipe_title">Swipe controls</string>
|
||||
<string name="revanced_swipe_volume_summary_off">Swipe controls for volume are disabled</string>
|
||||
<string name="revanced_swipe_volume_summary_on">Swipe controls for volume are enabled</string>
|
||||
<string name="revanced_swipe_volume_title">Swipe controls for Volume</string>
|
||||
<string name="revanced_swipe_pts_title">Press-to-Swipe</string>
|
||||
<string name="revanced_swipe_pts_summary_off">Swipe controls are always active</string>
|
||||
<string name="revanced_swipe_pts_summary_on">Swipe controls require a long-press before activating</string>
|
||||
<string name="revanced_swipe_pts_haptic_title">Vibrate on Press-to-Swipe</string>
|
||||
<string name="revanced_swipe_pts_haptic_summary_on">You\'ll get haptic feedback when activating Press-to-Swipe</string>
|
||||
<string name="revanced_swipe_pts_haptic_summary_off">You won\'t get haptic feedback when activating Press-to-Swipe</string>
|
||||
<string name="revanced_swipe_overlay_timeout_title">Overlay Timeout</string>
|
||||
<string name="revanced_swipe_overlay_timeout_summary">How long the overlay is shown after changes (ms)</string>
|
||||
<string name="revanced_swipe_overlay_text_size_title">Overlay Text Size</string>
|
||||
<string name="revanced_swipe_overlay_text_size_summary">Text size on the overlay</string>
|
||||
<string name="revanced_swipe_overlay_bg_alpha_title">Overlay Background Transparency</string>
|
||||
<string name="revanced_swipe_overlay_bg_alpha_summary">Transparency value of the overlay background (0–255)</string>
|
||||
<string name="revanced_swipe_magnitude_threshold_title">Swipe Magnitude Threshold</string>
|
||||
<string name="revanced_swipe_magnitude_threshold_summary">Minimum magnitude before a swipe is detected</string>
|
||||
<string name="revanced_swipe_tablet_title">Tablet style</string>
|
||||
<string name="revanced_swipe_tablet_summary_on">Tablet style is turned on. For example suggested videos are only partially working</string>
|
||||
<string name="revanced_swipe_tablet_summary_off">Tablet style is turned off</string>
|
||||
<string name="revanced_website_summary">Tap to open our website</string>
|
||||
<string name="revanced_website_title">ReVanced website</string>
|
||||
<string name="revanced_home_ads_summary_off">Home ADS are hidden</string>
|
||||
<string name="revanced_home_ads_summary_on">Home ADS are shown</string>
|
||||
<string name="revanced_home_ads_title">Home ADS</string>
|
||||
<string name="revanced_video_ads_title">Video ADS</string>
|
||||
<string name="revanced_video_ads_summary_off">Video ADS are hidden</string>
|
||||
<string name="revanced_video_ads_summary_on">Video ADS are shown</string>
|
||||
<string name="revanced_reel_summary_off">Stories are hidden</string>
|
||||
<string name="revanced_reel_summary_on">Stories are shown</string>
|
||||
<string name="revanced_reel_title">YouTube stories</string>
|
||||
<string name="revanced_ad_settings_title">AD settings</string>
|
||||
<string name="revanced_tablet_miniplayer_summary_off">Tablet miniplayer is not being used</string>
|
||||
<string name="revanced_tablet_miniplayer_summary_on">Tablet miniplayer is being used</string>
|
||||
<string name="revanced_tablet_miniplayer_title">Tablet miniplayer</string>
|
||||
|
||||
<string name="litho_comments">Comments removal</string>
|
||||
<string name="litho_comments_off">Comments removal is turned off (new comments / phones only)</string>
|
||||
<string name="litho_comments_on">Comments removal is turned on (new comments / phones only)</string>
|
||||
<string name="litho_community_posts">Community post removal</string>
|
||||
<string name="litho_community_posts_off">Community post removal is turned off</string>
|
||||
<string name="litho_community_posts_on">Community post removal is turned on</string>
|
||||
<string name="litho_compact_banner">Compact banner removal</string>
|
||||
<string name="litho_compact_banner_off">Compact banner removal is turned off</string>
|
||||
<string name="litho_compact_banner_on">Compact banner removal is turned on</string>
|
||||
<string name="litho_compact_movie">Compact movie removal</string>
|
||||
<string name="litho_compact_movie_off">Compact movie removal is turned off</string>
|
||||
<string name="litho_compact_movie_on">Compact movie removal is turned on</string>
|
||||
<string name="litho_general_ad_removal">General layout ad removal</string>
|
||||
<string name="litho_general_ad_removal_off">General layout ad removal is turned off</string>
|
||||
<string name="litho_general_ad_removal_on">General layout ad removal is turned on</string>
|
||||
<string name="litho_horizontal_movie_shelf">Movie shelf removal</string>
|
||||
<string name="litho_horizontal_movie_shelf_off">Movie shelf removal is turned off</string>
|
||||
<string name="litho_horizontal_movie_shelf_on">Movie shelf removal is turned on</string>
|
||||
<string name="litho_in_feed_survey">Survey removal</string>
|
||||
<string name="litho_in_feed_survey_off">Feed survey removal is turned off</string>
|
||||
<string name="litho_in_feed_survey_on">Feed survey removal is turned on</string>
|
||||
<string name="litho_merchandise">Merchandise removal</string>
|
||||
<string name="litho_merchandise_off">Merchandise removal is turned off</string>
|
||||
<string name="litho_merchandise_on">Merchandise removal is turned on</string>
|
||||
<string name="litho_movie_upsell">Movie upsell removal</string>
|
||||
<string name="litho_movie_upsell_off">Movie upsell removal is turned off</string>
|
||||
<string name="litho_movie_upsell_on">Movie upsell removal is turned on</string>
|
||||
<string name="litho_emergency_box">Emergency box removal</string>
|
||||
<string name="litho_emergency_box_on">Emergency box removal is turned on</string>
|
||||
<string name="litho_emergency_box_off">Emergency box removal is turned off</string>
|
||||
<string name="litho_info_panel">Info panel removal</string>
|
||||
<string name="litho_info_panel_on">Info panel removal is turned on</string>
|
||||
<string name="litho_info_panel_off">Info panel removal is turned off</string>
|
||||
<string name="litho_medical_panel">Medical panel removal</string>
|
||||
<string name="litho_medical_panel_on">Medical panel removal is turned on</string>
|
||||
<string name="litho_medical_panel_off">Medical panel removal is turned off</string>
|
||||
<string name="litho_paid_content">Paid content removal</string>
|
||||
<string name="litho_paid_content_on">Paid content removal is turned on</string>
|
||||
<string name="litho_paid_content_off">Paid content removal is turned off</string>
|
||||
<string name="litho_suggested">Suggested for you removal</string>
|
||||
<string name="litho_suggested_on">Suggested for you removal is turned on</string>
|
||||
<string name="litho_suggested_off">Suggested for you removal is turned off</string>
|
||||
<string name="litho_hide_suggestions">General Suggestions removal</string>
|
||||
<string name="litho_hide_suggestions_on">General Suggestions removal is turned on</string>
|
||||
<string name="litho_hide_suggestions_off">General Suggestions removal is turned off</string>
|
||||
<string name="litho_latest_posts">Latest posts removal</string>
|
||||
<string name="litho_latest_posts_on">Latest posts removal is turned on</string>
|
||||
<string name="litho_latest_posts_off">Latest posts removal is turned off</string>
|
||||
<string name="litho_channel_guidelines">Channel guidelines removal</string>
|
||||
<string name="litho_channel_guidelines_on">Channel guidelines removal is turned on</string>
|
||||
<string name="litho_channel_guidelines_off">Channel guidelines removal is turned off</string>
|
||||
|
||||
<string name="microg_notification_settings">Notification settings</string>
|
||||
<string name="microg_notification_settings_summary">"1. Google device registration and Cloud Messaging need to be enabled for notifications.
|
||||
2. ReVanced needs to be shown as registered under Cloud Messaging.
|
||||
3. Current State in Cloud Messaging must be Connected."</string>
|
||||
<string name="microg_settings">MicroG settings</string>
|
||||
<string name="revanced_settings">ReVanced settings</string>
|
||||
|
||||
<string name="revanced_seekbar_tapping">Seekbar Tapping</string>
|
||||
<string name="revanced_seekbar_tapping_off">Seekbar Tapping (video progress bar) is disabled</string>
|
||||
<string name="revanced_seekbar_tapping_on">Seekbar Tapping (video progress bar) is enabled</string>
|
||||
|
||||
<string name="revanced_minimized_playback">Background playback</string>
|
||||
<string name="revanced_minimized_playback_off">Background playback is disabled</string>
|
||||
<string name="revanced_minimized_playback_on">Background playback is enabled</string>
|
||||
|
||||
<string name="pref_subtitles_scale_normal">Normal</string>
|
||||
|
||||
<string name="litho_shorts_shelf">Shorts Shelf</string>
|
||||
<string name="litho_shorts_shelf_off">Shorts Shelf removal is turned off</string>
|
||||
<string name="litho_shorts_shelf_on">Shorts Shelf removal is turned on</string>
|
||||
|
||||
<string name="revanced_create_button_summary_off">Create Button is hidden</string>
|
||||
<string name="revanced_create_button_summary_on">Create Button is shown</string>
|
||||
<string name="revanced_create_button_title">Create Button</string>
|
||||
|
||||
<string name="litho_community_guidelines">Community Guidelines</string>
|
||||
<string name="litho_community_guidelines_off">Community Guidelines removal is turned off</string>
|
||||
<string name="litho_community_guidelines_on">Community Guidelines removal is turned on</string>
|
||||
|
||||
<string name="revanced_copy_video_url_summary_off">Copy Link Button is hidden from the player overlay</string>
|
||||
<string name="revanced_copy_video_url_summary_on">Copy Link Button is shown in the player overlay</string>
|
||||
<string name="revanced_copy_video_url_timestamp_summary_off">Copy Link Button With Timestamp is hidden from the player overlay</string>
|
||||
<string name="revanced_copy_video_url_timestamp_summary_on">Copy Link Button With Timestamp is shown in the player overlay</string>
|
||||
<string name="revanced_copy_video_url_timestamp_title">Copy Link Button With Timestamp</string>
|
||||
<string name="revanced_copy_video_url_title">Copy Link Button</string>
|
||||
|
||||
<string name="revanced_old_style_quality_settings_title">Quality Settings style</string>
|
||||
<string name="revanced_old_style_quality_settings_summary_off">Using default style video quality settings</string>
|
||||
<string name="revanced_old_style_quality_settings_summary_on">Using old style video quality settings</string>
|
||||
|
||||
<string name="revanced_videoadwhitelisting_title">Video ad whitelisting</string>
|
||||
<string name="revanced_videoadwhitelisting_summary_off">Video ad whitelisting is turned off</string>
|
||||
<string name="revanced_videoadwhitelisting_summary_on">Video ad whitelisting is turned on. Use the ADS button under the player to whitelist a channel</string>
|
||||
<string name="revanced_whitelisting_ads">ADS</string>
|
||||
<string name="revanced_whitelisting_sponsorblock">SponsorBlock</string>
|
||||
<string name="revanced_whitelisting_added" formatted="false">Channel %s was added to the %s whitelist</string>
|
||||
<string name="revanced_whitelisting_removed" formatted="false">Channel %s was removed from the %s whitelist</string>
|
||||
<string name="revanced_whitelisting_add_failed" formatted="false">Failed to add channel %s to the %s whitelist</string>
|
||||
<string name="revanced_whitelisting_remove_failed" formatted="false">Failed to remove channel %s from the %s whitelist</string>
|
||||
<string name="revanced_whitelisting_fetch_failed" formatted="false">Failed to retrieve channel details, received code %d</string>
|
||||
<string name="revanced_button_location_entry_none">Hidden</string>
|
||||
<string name="revanced_button_location_entry_player">In player</string>
|
||||
<string name="revanced_button_location_entry_buttoncontainer">Under player</string>
|
||||
<string name="revanced_button_location_entry_both">Both</string>
|
||||
<string name="revanced_ryd_settings_title">Return YouTube Dislike settings</string>
|
||||
<string name="revanced_ryd_settings_summary">Uses the RYD API</string>
|
||||
<string name="sb_settings">SponsorBlock settings</string>
|
||||
<string name="sb_summary">Uses the sponsor.ajay.app API</string>
|
||||
<string name="revanced_ryd_title">Enable RYD</string>
|
||||
<string name="revanced_ryd_summary">Switch this on to see the dislike counts again</string>
|
||||
<string name="revanced_ryd_attribution_title">Return YouTube Dislike Integration</string>
|
||||
<string name="revanced_ryd_attribution_summary">This integration uses the RYD API from https://returnyoutubedislike.com. Tap to learn more</string>
|
||||
</resources>
|
@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<Preference android:title="@string/revanced_ryd_settings_title" android:summary="@string/revanced_ryd_settings_summary">
|
||||
<intent android:targetPackage="com.google.android.youtube" android:data="ryd_settings" android:targetClass="com.google.android.libraries.social.licenses.LicenseActivity"/>
|
||||
</Preference>
|
||||
<Preference android:title="@string/sb_settings" android:summary="@string/sb_summary">
|
||||
<intent android:targetPackage="com.google.android.youtube" android:data="sponsorblock_settings" android:targetClass="com.google.android.libraries.social.licenses.LicenseActivity"/>
|
||||
</Preference>
|
||||
<Preference android:title="@string/revanced_settings">
|
||||
<intent android:targetPackage="com.google.android.youtube" android:data="revanced_settings" android:targetClass="com.google.android.libraries.social.licenses.LicenseActivity"/>
|
||||
</Preference>
|
||||
</PreferenceScreen>
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:background="@color/yt_white1" android:layout_width="match_parent" android:layout_height="wrap_content" android:elevation="4dp">
|
||||
<android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:background="?attr/ytBrandBackgroundSolid" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:navigationIcon="@drawable/quantum_ic_arrow_back_white_24" app:title="ReVanced settings"/>
|
||||
<android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:background="?attr/ytBrandBackgroundSolid" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:navigationIcon="@drawable/quantum_ic_arrow_back_white_24" app:title="@string/revanced_settings"/>
|
||||
</FrameLayout>
|
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge>
|
||||
<include layout="@layout/revanced_settings_with_toolbar_layout"/>
|
||||
</merge>
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:fitsSystemWindows="true" android:layout_width="match_parent" android:layout_height="match_parent" android:transitionGroup="true">
|
||||
<include layout="@layout/xsettings_toolbar"/>
|
||||
<FrameLayout android:id="@+id/xsettings_fragments" android:layout_width="match_parent" android:layout_height="match_parent"/>
|
||||
<include layout="@layout/revanced_settings_toolbar"/>
|
||||
<FrameLayout android:id="@+id/revanced_settings_fragments" android:layout_width="match_parent" android:layout_height="match_parent"/>
|
||||
</LinearLayout>
|
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge>
|
||||
<include layout="@layout/xsettings_with_toolbar_layout"/>
|
||||
</merge>
|
@ -1,180 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:yt="http://schemas.android.com/apk/res-auto">
|
||||
<PreferenceCategory
|
||||
android:layout_height="match_parent"
|
||||
android:title="@string/revanced_settings" />
|
||||
<PreferenceScreen android:title="@string/revanced_codec_override_title" android:key="revanced_override_codec">
|
||||
<SwitchPreference android:title="@string/revanced_vp9_title" android:key="revanced_override_codec_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_vp9_summary_on" android:summaryOff="@string/revanced_vp9_summary_off" />
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen android:title="@string/revanced_video_settings_title" android:key="video_settings">
|
||||
<SwitchPreference android:title="@string/revanced_old_style_quality_settings_title" android:key="revanced_use_old_style_quality_settings" android:defaultValue="true" android:summaryOn="@string/revanced_old_style_quality_settings_summary_on" android:summaryOff="@string/revanced_old_style_quality_settings_summary_off" />
|
||||
<ListPreference android:title="@string/revanced_preferred_video_speed_title" android:key="revanced_pref_video_speed" android:summary="@string/revanced_preferred_video_speed_summary" />
|
||||
<!--<SwitchPreference android:title="Auto captions" android:key="revanced_pref_auto_captions" android:defaultValue="false" android:summaryOn="Auto captions are turned on" android:summaryOff="Auto captions are turned off" />-->
|
||||
</PreferenceScreen>
|
||||
<!--<PreferenceScreen android:title="@string/revanced_videoadwhitelisting_title" android:key="video_ad_settings">
|
||||
<SwitchPreference android:title="@string/revanced_videoadwhitelisting_title" android:key="revanced_whitelist_ads_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_videoadwhitelisting_summary_on" android:summaryOff="@string/revanced_videoadwhitelisting_summary_off" />
|
||||
</PreferenceScreen>-->
|
||||
<PreferenceScreen
|
||||
android:key="ad_settings"
|
||||
android:title="@string/revanced_ad_settings_title">
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="revanced_home_ads_enabled"
|
||||
android:summaryOff="@string/revanced_home_ads_summary_off"
|
||||
android:summaryOn="@string/revanced_home_ads_summary_on"
|
||||
android:title="@string/revanced_home_ads_title" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="revanced_video_ads_enabled"
|
||||
android:summaryOff="@string/revanced_video_ads_summary_off"
|
||||
android:summaryOn="@string/revanced_video_ads_summary_on"
|
||||
android:title="@string/revanced_video_ads_title" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_ad_removal"
|
||||
android:summaryOff="@string/litho_general_ad_removal_off"
|
||||
android:summaryOn="@string/litho_general_ad_removal_on"
|
||||
android:title="@string/litho_general_ad_removal" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_merchandise"
|
||||
android:summaryOff="@string/litho_merchandise_off"
|
||||
android:summaryOn="@string/litho_merchandise_on"
|
||||
android:title="@string/litho_merchandise" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_community_posts_removal"
|
||||
android:summaryOff="@string/litho_community_posts_off"
|
||||
android:summaryOn="@string/litho_community_posts_on"
|
||||
android:title="@string/litho_community_posts" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_compact_banner_removal"
|
||||
android:summaryOff="@string/litho_compact_banner_off"
|
||||
android:summaryOn="@string/litho_compact_banner_on"
|
||||
android:title="@string/litho_compact_banner" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="revanced_adremover_comments_removal"
|
||||
android:summaryOff="@string/litho_comments_off"
|
||||
android:summaryOn="@string/litho_comments_on"
|
||||
android:title="@string/litho_comments" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_movie"
|
||||
android:summaryOff="@string/litho_compact_movie_off"
|
||||
android:summaryOn="@string/litho_compact_movie_on"
|
||||
android:title="@string/litho_compact_movie" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_feed_survey"
|
||||
android:summaryOff="@string/litho_in_feed_survey_off"
|
||||
android:summaryOn="@string/litho_in_feed_survey_on"
|
||||
android:title="@string/litho_in_feed_survey" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_shorts_shelf"
|
||||
android:summaryOff="@string/litho_shorts_shelf_off"
|
||||
android:summaryOn="@string/litho_shorts_shelf_on"
|
||||
android:title="@string/litho_shorts_shelf" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_community_guideline"
|
||||
android:summaryOff="@string/litho_community_guidelines_off"
|
||||
android:summaryOn="@string/litho_community_guidelines_on"
|
||||
android:title="@string/litho_community_guidelines" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_emergency_box_removal"
|
||||
android:summaryOff="@string/litho_emergency_box_off"
|
||||
android:summaryOn="@string/litho_emergency_box_on"
|
||||
android:title="@string/litho_emergency_box" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_info_panel"
|
||||
android:summaryOff="@string/litho_info_panel_off"
|
||||
android:summaryOn="@string/litho_info_panel_on"
|
||||
android:title="@string/litho_info_panel" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_medical_panel"
|
||||
android:summaryOff="@string/litho_medical_panel_off"
|
||||
android:summaryOn="@string/litho_medical_panel_on"
|
||||
android:title="@string/litho_medical_panel" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_paid_content"
|
||||
android:summaryOff="@string/litho_paid_content_off"
|
||||
android:summaryOn="@string/litho_paid_content_on"
|
||||
android:title="@string/litho_paid_content" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_suggested"
|
||||
android:summaryOff="@string/litho_suggested_off"
|
||||
android:summaryOn="@string/litho_suggested_on"
|
||||
android:title="@string/litho_suggested" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_hide_suggestions"
|
||||
android:summaryOff="@string/litho_hide_suggestions_off"
|
||||
android:summaryOn="@string/litho_hide_suggestions_on"
|
||||
android:title="@string/litho_hide_suggestions" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_hide_latest_posts"
|
||||
android:summaryOff="@string/litho_latest_posts_off"
|
||||
android:summaryOn="@string/litho_latest_posts_on"
|
||||
android:title="@string/litho_latest_posts" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="revanced_adremover_hide_channel_guidelines"
|
||||
android:summaryOff="@string/litho_channel_guidelines_off"
|
||||
android:summaryOn="@string/litho_channel_guidelines_on"
|
||||
android:title="@string/litho_channel_guidelines" />
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen android:title="@string/revanced_layout_settings_title" android:key="layout_settings">
|
||||
<SwitchPreference android:title="@string/revanced_reel_title" android:key="revanced_reel_button_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_reel_summary_on" android:summaryOff="@string/revanced_reel_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_suggestion_title" android:key="revanced_info_cards_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_suggestion_summary_on" android:summaryOff="@string/revanced_suggestion_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_branding_watermark_title" android:key="revanced_branding_watermark_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_branding_watermark_summary_on" android:summaryOff="@string/revanced_branding_watermark_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_cast_button_title" android:key="revanced_cast_button_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_cast_button_summary_on" android:summaryOff="@string/revanced_cast_button_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_autoplay_button_title" android:key="revanced_autoplay_button_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_autoplay_button_summary_on" android:summaryOff="@string/revanced_autoplay_button_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_tablet_miniplayer_title" android:key="revanced_tablet_miniplayer" android:defaultValue="false" android:summaryOn="@string/revanced_tablet_miniplayer_summary_on" android:summaryOff="@string/revanced_tablet_miniplayer_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_create_button_title" android:key="revanced_create_button_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_create_button_summary_on" android:summaryOff="@string/revanced_create_button_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_new_actionbar_title" android:key="revanced_new_actionbar" android:defaultValue="false" android:summaryOn="@string/revanced_new_actionbar_summary_on" android:summaryOff="@string/revanced_new_actionbar_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_shorts_button_title" android:key="revanced_shorts_button_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_shorts_button_summary_on" android:summaryOff="@string/revanced_shorts_button_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_fullscreen_panels_title" android:key="revanced_fullscreen_panels_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_fullscreen_panels_summary_on" android:summaryOff="@string/revanced_fullscreen_panels_summary_off" />
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen android:title="@string/revanced_misc_title" android:key="misc_screen">
|
||||
<SwitchPreference android:title="@string/revanced_auto_repeat_title" android:key="revanced_pref_auto_repeat" android:defaultValue="false" android:summaryOn="@string/revanced_auto_repeat_summary_on" android:summaryOff="@string/revanced_auto_repeat_summary_off" />
|
||||
<!--<ListPreference android:entries="@array/revanced_button_location_entries" android:title="@string/revanced_copy_video_url_timestamp_title" android:key="revanced_pref_copy_video_url_timestamp_button_list" android:entryValues="@array/revanced_button_location_entry_values" />
|
||||
<ListPreference android:entries="@array/revanced_button_location_entries" android:title="@string/revanced_copy_video_url_title" android:key="revanced_pref_copy_video_url_button_list" android:entryValues="@array/revanced_button_location_entry_values" />-->
|
||||
<SwitchPreference android:title="@string/revanced_hdr_full_brightness_title" android:key="revanced_pref_hdr_autobrightness" android:defaultValue="false" android:summaryOn="@string/revanced_hdr_full_brightness_summary_on" android:summaryOff="@string/revanced_hdr_full_brightness_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_seekbar_tapping" android:key="revanced_enable_tap_seeking" android:defaultValue="true" android:summaryOn="@string/revanced_seekbar_tapping_on" android:summaryOff="@string/revanced_seekbar_tapping_off" />
|
||||
<SwitchPreference android:title="@string/revanced_minimized_playback" android:key="revanced_enable_minimized_playback" android:defaultValue="true" android:summaryOn="@string/revanced_minimized_playback_on" android:summaryOff="@string/revanced_minimized_playback_off" />
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen android:title="@string/revanced_swipe_title" android:key="swipe_screen" android:summary="@string/revanced_swipe_screen_summary">
|
||||
<SwitchPreference android:title="@string/revanced_swipe_brightness_title" android:key="revanced_enable_swipe_brightness" android:defaultValue="false" android:summaryOn="@string/revanced_swipe_brightness_summary_on" android:summaryOff="@string/revanced_swipe_brightness_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_swipe_volume_title" android:key="revanced_enable_swipe_volume" android:defaultValue="false" android:summaryOn="@string/revanced_swipe_volume_summary_on" android:summaryOff="@string/revanced_swipe_volume_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_swipe_pts_title" android:key="revanced_enable_press_to_swipe" android:defaultValue="false" android:summaryOn="@string/revanced_swipe_pts_summary_on" android:summaryOff="@string/revanced_swipe_pts_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_swipe_pts_haptic_title" android:key="revanced_enable_swipe_haptic_feedback" android:defaultValue="false" android:summaryOn="@string/revanced_swipe_pts_haptic_summary_on" android:summaryOff="@string/revanced_swipe_pts_haptic_summary_off" />
|
||||
<EditTextPreference android:inputType="number" android:title="@string/revanced_swipe_overlay_timeout_title" android:key="revanced_swipe_overlay_timeout" android:summary="@string/revanced_swipe_overlay_timeout_summary" android:defaultValue="500" />
|
||||
<EditTextPreference android:inputType="number" android:title="@string/revanced_swipe_overlay_text_size_title" android:key="revanced_swipe_overlay_text_size" android:summary="@string/revanced_swipe_overlay_text_size_summary" android:defaultValue="22" />
|
||||
<EditTextPreference android:inputType="number" android:title="@string/revanced_swipe_overlay_bg_alpha_title" android:key="revanced_swipe_overlay_background_alpha" android:summary="@string/revanced_swipe_overlay_bg_alpha_summary" android:defaultValue="127" />
|
||||
<EditTextPreference android:inputType="number" android:title="@string/revanced_swipe_magnitude_threshold_title" android:key="revanced_swipe_magnitude_threshold" android:summary="@string/revanced_swipe_magnitude_threshold_summary" android:defaultValue="30" />
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen android:title="@string/revanced_buffer_title" android:key="buffer_screen">
|
||||
<EditTextPreference android:inputType="number" android:title="@string/revanced_maximum_buffer_title" android:key="revanced_pref_max_buffer_ms" android:summary="@string/revanced_maximum_buffer_summary" android:defaultValue="120000" />
|
||||
<EditTextPreference android:inputType="number" android:title="@string/revanced_playback_start_title" android:key="revanced_pref_buffer_for_playback_ms" android:summary="@string/revanced_playback_start_summary" android:defaultValue="2500" />
|
||||
<EditTextPreference android:inputType="number" android:title="@string/revanced_rebuffer_title" android:key="revanced_pref_buffer_for_playback_after_rebuffer_ms" android:summary="@string/revanced_rebuffer_summary" android:defaultValue="5000" />
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen android:title="@string/revanced_support_title" android:key="support_screen" android:summary="@string/revanced_support_summary">
|
||||
<Preference android:title="@string/revanced_discord_title" android:summary="@string/revanced_discord_summary">
|
||||
<intent android:action="android.intent.action.VIEW" android:data="https://discord.gg/rF2YcEjcrT" />
|
||||
</Preference>
|
||||
<Preference android:title="@string/revanced_website_title" android:summary="@string/revanced_website_summary">
|
||||
<intent android:action="android.intent.action.VIEW" android:data="https://revanced.app" />
|
||||
</Preference>
|
||||
</PreferenceScreen>
|
||||
<SwitchPreference android:title="@string/revanced_debug_title" android:key="revanced_debug_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_debug_summary_on" android:summaryOff="@string/revanced_debug_summary_off" />
|
||||
</PreferenceScreen>
|
Binary file not shown.
After Width: | Height: | Size: 357 B |
Loading…
Reference in New Issue
Block a user