mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-07 01:51:27 +01:00
feat(YouTube - Loop video): Add player button to change loop video state (#5961)
This commit is contained in:
@@ -1,11 +0,0 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class AutoRepeatPatch {
|
||||
//Used by app.revanced.patches.youtube.layout.autorepeat.patch.AutoRepeatPatch
|
||||
public static boolean shouldAutoRepeat() {
|
||||
return Settings.AUTO_REPEAT.get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class LoopVideoPatch {
|
||||
/**
|
||||
* Injection point
|
||||
*/
|
||||
public static boolean shouldLoopVideo() {
|
||||
return Settings.LOOP_VIDEO.get();
|
||||
}
|
||||
}
|
||||
@@ -341,7 +341,8 @@ public class Settings extends BaseSettings {
|
||||
// Miscellaneous
|
||||
public static final BooleanSetting ANNOUNCEMENTS = new BooleanSetting("revanced_announcements", TRUE);
|
||||
public static final IntegerSetting ANNOUNCEMENT_LAST_ID = new IntegerSetting("revanced_announcement_last_id", -1, false, false);
|
||||
public static final BooleanSetting AUTO_REPEAT = new BooleanSetting("revanced_auto_repeat", FALSE);
|
||||
public static final BooleanSetting LOOP_VIDEO = new BooleanSetting("revanced_loop_video", FALSE);
|
||||
public static final BooleanSetting LOOP_VIDEO_BUTTON = new BooleanSetting("revanced_loop_video_button", FALSE);
|
||||
public static final BooleanSetting BYPASS_URL_REDIRECTS = new BooleanSetting("revanced_bypass_url_redirects", TRUE);
|
||||
public static final BooleanSetting CHECK_WATCH_HISTORY_DOMAIN_NAME = new BooleanSetting("revanced_check_watch_history_domain_name", TRUE, false, false);
|
||||
public static final BooleanSetting DISABLE_HAPTIC_FEEDBACK_CHAPTERS = new BooleanSetting("revanced_disable_haptic_feedback_chapters", FALSE);
|
||||
@@ -444,28 +445,30 @@ public class Settings extends BaseSettings {
|
||||
public static final StringSetting SB_CATEGORY_UNSUBMITTED_COLOR = new StringSetting("sb_unsubmitted_color", "#FFFFFFFF", false, false);
|
||||
|
||||
// Deprecated migrations
|
||||
private static final BooleanSetting DEPRECATED_AUTO_REPEAT = new BooleanSetting("revanced_auto_repeat", FALSE);
|
||||
private static final BooleanSetting DEPRECATED_HIDE_PLAYER_BUTTONS = new BooleanSetting("revanced_hide_player_buttons", FALSE, true);
|
||||
private static final BooleanSetting DEPRECATED_HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER = new BooleanSetting("revanced_hide_video_quality_menu_footer", FALSE);
|
||||
private static final IntegerSetting DEPRECATED_SWIPE_OVERLAY_BACKGROUND_ALPHA = new IntegerSetting("revanced_swipe_overlay_background_alpha", 127);
|
||||
private static final StringSetting DEPRECATED_SEEKBAR_CUSTOM_COLOR_PRIMARY = new StringSetting("revanced_seekbar_custom_color_value", "#FF0033");
|
||||
private static final StringSetting DEPRECATED_SEEKBAR_CUSTOM_COLOR_PRIMARY = new StringSetting("revanced_seekbar_custom_color_value", "#FF0033");
|
||||
private static final BooleanSetting DEPRECATED_DISABLE_SUGGESTED_VIDEO_END_SCREEN = new BooleanSetting("revanced_disable_suggested_video_end_screen", FALSE);
|
||||
private static final BooleanSetting DEPRECATED_RESTORE_OLD_VIDEO_QUALITY_MENU = new BooleanSetting("revanced_restore_old_video_quality_menu", TRUE);
|
||||
private static final BooleanSetting DEPRECATED_AUTO_CAPTIONS = new BooleanSetting("revanced_auto_captions", FALSE);
|
||||
|
||||
public static final FloatSetting DEPRECATED_SB_CATEGORY_SPONSOR_OPACITY = new FloatSetting("sb_sponsor_opacity", 0.8f, false, false);
|
||||
public static final FloatSetting DEPRECATED_SB_CATEGORY_SELF_PROMO_OPACITY = new FloatSetting("sb_selfpromo_opacity", 0.8f, false, false);
|
||||
public static final FloatSetting DEPRECATED_SB_CATEGORY_INTERACTION_OPACITY = new FloatSetting("sb_interaction_opacity", 0.8f, false, false);
|
||||
public static final FloatSetting DEPRECATED_SB_CATEGORY_HIGHLIGHT_OPACITY = new FloatSetting("sb_highlight_opacity", 0.8f, false, false);
|
||||
public static final FloatSetting DEPRECATED_SB_CATEGORY_HOOK_OPACITY = new FloatSetting("sb_hook_opacity", 0.8f, false, false);
|
||||
public static final FloatSetting DEPRECATED_SB_CATEGORY_INTRO_OPACITY = new FloatSetting("sb_intro_opacity", 0.8f, false, false);
|
||||
public static final FloatSetting DEPRECATED_SB_CATEGORY_OUTRO_OPACITY = new FloatSetting("sb_outro_opacity", 0.8f, false, false);
|
||||
public static final FloatSetting DEPRECATED_SB_CATEGORY_PREVIEW_OPACITY = new FloatSetting("sb_preview_opacity", 0.8f, false, false);
|
||||
public static final FloatSetting DEPRECATED_SB_CATEGORY_FILLER_OPACITY = new FloatSetting("sb_filler_opacity", 0.8f, false, false);
|
||||
public static final FloatSetting DEPRECATED_SB_CATEGORY_MUSIC_OFFTOPIC_OPACITY = new FloatSetting("sb_music_offtopic_opacity", 0.8f, false, false);
|
||||
private static final FloatSetting DEPRECATED_SB_CATEGORY_SPONSOR_OPACITY = new FloatSetting("sb_sponsor_opacity", 0.8f, false, false);
|
||||
private static final FloatSetting DEPRECATED_SB_CATEGORY_SELF_PROMO_OPACITY = new FloatSetting("sb_selfpromo_opacity", 0.8f, false, false);
|
||||
private static final FloatSetting DEPRECATED_SB_CATEGORY_INTERACTION_OPACITY = new FloatSetting("sb_interaction_opacity", 0.8f, false, false);
|
||||
private static final FloatSetting DEPRECATED_SB_CATEGORY_HIGHLIGHT_OPACITY = new FloatSetting("sb_highlight_opacity", 0.8f, false, false);
|
||||
private static final FloatSetting DEPRECATED_SB_CATEGORY_HOOK_OPACITY = new FloatSetting("sb_hook_opacity", 0.8f, false, false);
|
||||
private static final FloatSetting DEPRECATED_SB_CATEGORY_INTRO_OPACITY = new FloatSetting("sb_intro_opacity", 0.8f, false, false);
|
||||
private static final FloatSetting DEPRECATED_SB_CATEGORY_OUTRO_OPACITY = new FloatSetting("sb_outro_opacity", 0.8f, false, false);
|
||||
private static final FloatSetting DEPRECATED_SB_CATEGORY_PREVIEW_OPACITY = new FloatSetting("sb_preview_opacity", 0.8f, false, false);
|
||||
private static final FloatSetting DEPRECATED_SB_CATEGORY_FILLER_OPACITY = new FloatSetting("sb_filler_opacity", 0.8f, false, false);
|
||||
private static final FloatSetting DEPRECATED_SB_CATEGORY_MUSIC_OFFTOPIC_OPACITY = new FloatSetting("sb_music_offtopic_opacity", 0.8f, false, false);
|
||||
|
||||
static {
|
||||
// region Migration
|
||||
|
||||
migrateOldSettingToNew(DEPRECATED_AUTO_REPEAT, LOOP_VIDEO);
|
||||
migrateOldSettingToNew(DEPRECATED_HIDE_PLAYER_BUTTONS, HIDE_PLAYER_PREVIOUS_NEXT_BUTTONS);
|
||||
migrateOldSettingToNew(DEPRECATED_HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER, HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER);
|
||||
migrateOldSettingToNew(DEPRECATED_DISABLE_SUGGESTED_VIDEO_END_SCREEN, HIDE_END_SCREEN_SUGGESTED_VIDEO);
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package app.revanced.extension.youtube.videoplayer;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
|
||||
import android.view.View;
|
||||
import androidx.annotation.Nullable;
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class LoopVideoButton {
|
||||
@Nullable
|
||||
private static PlayerControlButton instance;
|
||||
|
||||
private static final int LOOP_VIDEO_ON = Utils.getResourceIdentifierOrThrow(
|
||||
"revanced_loop_video_button_on", "drawable");
|
||||
private static final int LOOP_VIDEO_OFF = Utils.getResourceIdentifierOrThrow(
|
||||
"revanced_loop_video_button_off", "drawable");
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void initializeButton(View controlsView) {
|
||||
try {
|
||||
instance = new PlayerControlButton(
|
||||
controlsView,
|
||||
"revanced_loop_video_button",
|
||||
null,
|
||||
Settings.LOOP_VIDEO_BUTTON::get,
|
||||
v -> updateButtonAppearance(),
|
||||
null
|
||||
);
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "initializeButton failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* injection point.
|
||||
*/
|
||||
public static void setVisibilityNegatedImmediate() {
|
||||
if (instance != null) instance.setVisibilityNegatedImmediate();
|
||||
}
|
||||
|
||||
/**
|
||||
* injection point.
|
||||
*/
|
||||
public static void setVisibilityImmediate(boolean visible) {
|
||||
if (instance != null) instance.setVisibilityImmediate(visible);
|
||||
}
|
||||
|
||||
/**
|
||||
* injection point.
|
||||
*/
|
||||
public static void setVisibility(boolean visible, boolean animated) {
|
||||
if (instance != null) instance.setVisibility(visible, animated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the button's appearance.
|
||||
*/
|
||||
private static void updateButtonAppearance() {
|
||||
if (instance == null) return;
|
||||
|
||||
try {
|
||||
Utils.verifyOnMainThread();
|
||||
|
||||
final boolean currentState = Settings.LOOP_VIDEO.get();
|
||||
final boolean newState = !currentState;
|
||||
Settings.LOOP_VIDEO.save(newState);
|
||||
|
||||
instance.setIcon(newState
|
||||
? LOOP_VIDEO_ON
|
||||
: LOOP_VIDEO_OFF);
|
||||
Utils.showToastShort(str(newState
|
||||
? "revanced_loop_video_button_toast_on"
|
||||
: "revanced_loop_video_button_toast_off"));
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "updateButtonAppearance failure", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1610,6 +1610,10 @@ public final class app/revanced/patches/youtube/misc/litho/filter/LithoFilterPat
|
||||
public static final fun getLithoFilterPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/loopvideo/LoopVideoPatchKt {
|
||||
public static final fun getLoopVideoPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatchKt {
|
||||
public static field hookNavigationButtonCreated Lkotlin/jvm/functions/Function1;
|
||||
public static final fun getHookNavigationButtonCreated ()Lkotlin/jvm/functions/Function1;
|
||||
|
||||
@@ -9,8 +9,8 @@ import app.revanced.patches.youtube.misc.playercontrols.playerControlsPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.shared.autoRepeatFingerprint
|
||||
import app.revanced.patches.youtube.shared.autoRepeatParentFingerprint
|
||||
import app.revanced.patches.youtube.shared.loopVideoFingerprint
|
||||
import app.revanced.patches.youtube.shared.loopVideoParentFingerprint
|
||||
import app.revanced.util.addInstructionsAtControlFlowLabel
|
||||
|
||||
@Suppress("unused")
|
||||
@@ -50,7 +50,7 @@ internal val exitFullscreenPatch = bytecodePatch(
|
||||
ListPreference("revanced_exit_fullscreen")
|
||||
)
|
||||
|
||||
autoRepeatFingerprint.match(autoRepeatParentFingerprint.originalClassDef).method.apply {
|
||||
loopVideoFingerprint.match(loopVideoParentFingerprint.originalClassDef).method.apply {
|
||||
addInstructionsAtControlFlowLabel(
|
||||
implementation!!.instructions.lastIndex,
|
||||
"invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->endOfVideoReached()V",
|
||||
|
||||
@@ -1,62 +1,9 @@
|
||||
package app.revanced.patches.youtube.misc.autorepeat
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.shared.autoRepeatFingerprint
|
||||
import app.revanced.patches.youtube.shared.autoRepeatParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.loopvideo.loopVideoPatch
|
||||
|
||||
// TODO: Rename this patch to AlwaysRepeatPatch (as well as strings and references in the extension).
|
||||
val autoRepeatPatch = bytecodePatch(
|
||||
name = "Always repeat",
|
||||
description = "Adds an option to always repeat videos when they end.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
addResourcesPatch,
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"20.07.39",
|
||||
"20.13.41",
|
||||
"20.14.43",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("youtube", "misc.autorepeat.autoRepeatPatch")
|
||||
|
||||
PreferenceScreen.MISC.addPreferences(
|
||||
SwitchPreference("revanced_auto_repeat"),
|
||||
)
|
||||
|
||||
autoRepeatFingerprint.match(autoRepeatParentFingerprint.originalClassDef).method.apply {
|
||||
val playMethod = autoRepeatParentFingerprint.method
|
||||
val index = instructions.lastIndex
|
||||
|
||||
// Remove return-void.
|
||||
removeInstruction(index)
|
||||
// Add own instructions there.
|
||||
addInstructionsWithLabels(
|
||||
index,
|
||||
"""
|
||||
invoke-static {}, Lapp/revanced/extension/youtube/patches/AutoRepeatPatch;->shouldAutoRepeat()Z
|
||||
move-result v0
|
||||
if-eqz v0, :noautorepeat
|
||||
invoke-virtual { p0 }, $playMethod
|
||||
:noautorepeat
|
||||
return-void
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
@Deprecated("Patch was renamed", ReplaceWith("looVideoPatch"))
|
||||
val autoRepeatPatch = bytecodePatch {
|
||||
dependsOn(loopVideoPatch)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package app.revanced.patches.youtube.misc.loopvideo
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.loopvideo.button.loopVideoButtonPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.shared.loopVideoFingerprint
|
||||
import app.revanced.patches.youtube.shared.loopVideoParentFingerprint
|
||||
import app.revanced.util.addInstructionsAtControlFlowLabel
|
||||
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/LoopVideoPatch;"
|
||||
|
||||
val loopVideoPatch = bytecodePatch(
|
||||
name = "Loop video",
|
||||
description = "Adds an option to loop videos and display loop video button in the video player.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
addResourcesPatch,
|
||||
loopVideoButtonPatch
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"20.07.39",
|
||||
"20.13.41",
|
||||
"20.14.43",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("youtube", "misc.loopvideo.loopVideoPatch")
|
||||
|
||||
PreferenceScreen.MISC.addPreferences(
|
||||
SwitchPreference("revanced_loop_video"),
|
||||
)
|
||||
|
||||
loopVideoFingerprint.match(loopVideoParentFingerprint.originalClassDef).method.apply {
|
||||
val playMethod = loopVideoParentFingerprint.method
|
||||
val insertIndex = indexOfFirstInstructionReversedOrThrow(Opcode.RETURN_VOID)
|
||||
|
||||
addInstructionsAtControlFlowLabel(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->shouldLoopVideo()Z
|
||||
move-result v0
|
||||
if-eqz v0, :do_not_loop
|
||||
invoke-virtual { p0 }, $playMethod
|
||||
:do_not_loop
|
||||
nop
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package app.revanced.patches.youtube.misc.loopvideo.button
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playercontrols.*
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.copyResources
|
||||
|
||||
private val loopVideoButtonResourcePatch = resourcePatch {
|
||||
dependsOn(playerControlsResourcePatch)
|
||||
|
||||
execute {
|
||||
copyResources(
|
||||
"loopvideobutton",
|
||||
ResourceGroup(
|
||||
"drawable",
|
||||
"revanced_loop_video_button_on.xml",
|
||||
"revanced_loop_video_button_off.xml"
|
||||
)
|
||||
)
|
||||
|
||||
addBottomControl("loopvideobutton")
|
||||
}
|
||||
}
|
||||
|
||||
private const val LOOP_VIDEO_BUTTON_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/videoplayer/LoopVideoButton;"
|
||||
|
||||
internal val loopVideoButtonPatch = bytecodePatch(
|
||||
description = "Adds the option to display loop video button in the video player.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
loopVideoButtonResourcePatch,
|
||||
playerControlsPatch,
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("youtube", "misc.loopvideo.button.loopVideoButtonPatch")
|
||||
|
||||
PreferenceScreen.PLAYER.addPreferences(
|
||||
SwitchPreference("revanced_loop_video_button"),
|
||||
)
|
||||
|
||||
// Initialize the button using standard approach.
|
||||
initializeBottomControl(LOOP_VIDEO_BUTTON_CLASS_DESCRIPTOR)
|
||||
injectVisibilityCheckCall(LOOP_VIDEO_BUTTON_CLASS_DESCRIPTOR)
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,10 @@ internal val conversionContextFingerprintToString = fingerprint {
|
||||
}
|
||||
}
|
||||
|
||||
internal val autoRepeatFingerprint = fingerprint {
|
||||
/**
|
||||
* Resolves to class found in [loopVideoParentFingerprint].
|
||||
*/
|
||||
internal val loopVideoFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
parameters()
|
||||
@@ -30,7 +33,7 @@ internal val autoRepeatFingerprint = fingerprint {
|
||||
}
|
||||
}
|
||||
|
||||
internal val autoRepeatParentFingerprint = fingerprint {
|
||||
internal val loopVideoParentFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
strings(
|
||||
|
||||
@@ -1526,10 +1526,17 @@ Tap here to learn more about DeArrow"</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_message">Your watch history is not being saved.<br><br>This most likely is caused by a DNS ad blocker or network proxy.<br><br>To fix this, whitelist <b>s.youtube.com</b> or turn off all DNS blockers and proxies.</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_ignore">Do not show again</string>
|
||||
</patch>
|
||||
<patch id="misc.autorepeat.autoRepeatPatch">
|
||||
<string name="revanced_auto_repeat_title">Enable auto-repeat</string>
|
||||
<string name="revanced_auto_repeat_summary_on">Auto-repeat is enabled</string>
|
||||
<string name="revanced_auto_repeat_summary_off">Auto-repeat is disabled</string>
|
||||
<patch id="misc.loopvideo.loopVideoPatch">
|
||||
<string name="revanced_loop_video_title">Enable loop video</string>
|
||||
<string name="revanced_loop_video_summary_on">Video will loop</string>
|
||||
<string name="revanced_loop_video_summary_off">Video will not loop</string>
|
||||
</patch>
|
||||
<patch id="misc.loopvideo.button.loopVideoButtonPatch">
|
||||
<string name="revanced_loop_video_button_title">Show loop video button</string>
|
||||
<string name="revanced_loop_video_button_summary_on">Button is shown</string>
|
||||
<string name="revanced_loop_video_button_summary_off">Button is not shown</string>
|
||||
<string name="revanced_loop_video_button_toast_on">Loop video is on</string>
|
||||
<string name="revanced_loop_video_button_toast_off">Loop video is off</string>
|
||||
</patch>
|
||||
<patch id="misc.dimensions.spoof.spoofDeviceDimensionsPatch">
|
||||
<string name="revanced_spoof_device_dimensions_title">Spoof device dimensions</string>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:fillAlpha="0.6"
|
||||
android:strokeAlpha="0.6"
|
||||
android:pathData="M17.6914,2.19922 L16.9844,2.91797 L19.0625,5 L3.61719,5 C3.15625,5,2.76953,5.14844,2.46094,5.46094 C2.15234,5.76562,2,6.15234,2,6.61719 L2,10 L3,10 L3,6.61719 C3,6.43359,3.05859,6.28516,3.17188,6.17188 C3.28906,6.05859,3.4375,6,3.61719,6 L19.0703,6 L19.0703,6.00781 L16.9844,8.09375 L17.6914,8.8125 L21,5.50781 L17.6914,2.19922 Z M21,14 L21,17.3828 C21,17.5625,20.9414,17.7109,20.8281,17.8281 C20.7109,17.9414,20.5625,18,20.3828,18 L4.92969,18 L4.92969,17.9922 L7.01563,15.9023 L6.30859,15.1836 L3,18.4922 L6.30859,21.7969 L7.01563,21.0781 L4.9375,19 L20.3828,19 C20.8438,19,21.2305,18.8477,21.5391,18.5391 C21.8477,18.2305,22,17.8438,22,17.3828 L22,14 L21,14 Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M17.6914,2.19922 L16.9844,2.91797 L19.0625,5 L3.61719,5 C3.15625,5,2.76953,5.14844,2.46094,5.46094 C2.15234,5.76562,2,6.15234,2,6.61719 L2,10 L3,10 L3,6.61719 C3,6.43359,3.05859,6.28516,3.17188,6.17188 C3.28906,6.05859,3.4375,6,3.61719,6 L19.0703,6 L19.0703,6.00781 L16.9844,8.09375 L17.6914,8.8125 L21,5.50781 L17.6914,2.19922 Z M12.7168,8.30078 L10.4609,9.28906 L10.4609,10.1152 L11.9746,9.44336 L11.9746,15.543 L12.8496,15.543 L12.8496,8.30078 L12.7168,8.30078 Z M21,14 L21,17.3828 C21,17.5625,20.9414,17.7109,20.8281,17.8281 C20.7109,17.9414,20.5625,18,20.3828,18 L4.92969,18 L4.92969,17.9922 L7.01563,15.9023 L6.30859,15.1836 L3,18.4922 L6.30859,21.7969 L7.01563,21.0781 L4.9375,19 L20.3828,19 C20.8438,19,21.2305,18.8477,21.5391,18.5391 C21.8477,18.2305,22,17.8438,22,17.3828 L22,14 L21,14 Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:yt="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/youtube_controls_bottom_ui_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layoutDirection="ltr">
|
||||
|
||||
<com.google.android.libraries.youtube.common.ui.TouchImageView
|
||||
android:id="@+id/revanced_loop_video_button"
|
||||
style="@style/YouTubePlayerButton"
|
||||
android:layout_width="48.0dip"
|
||||
android:layout_height="60.0dip"
|
||||
android:paddingTop="6.0dp"
|
||||
android:paddingBottom="0dp"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/revanced_loop_video_button_off"
|
||||
yt:layout_constraintBottom_toTopOf="@+id/quick_actions_container"
|
||||
yt:layout_constraintRight_toLeftOf="@+id/fullscreen_button" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
Reference in New Issue
Block a user