feat(YouTube - Loop video): Add player button to change loop video state (#5961)
This commit is contained in:
+3
-3
@@ -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",
|
||||
|
||||
+4
-57
@@ -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
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+57
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user