Skip to content

Commit 296d63b

Browse files
feat(YouTube): Add Open videos fullscreen patch (#4069)
Co-authored-by: oSumAtrIX <[email protected]>
1 parent 0b2af47 commit 296d63b

File tree

12 files changed

+136
-72
lines changed

12 files changed

+136
-72
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package app.revanced.extension.youtube.patches;
2+
3+
import app.revanced.extension.youtube.settings.Settings;
4+
5+
@SuppressWarnings("unused")
6+
public class OpenVideosFullscreen {
7+
8+
/**
9+
* Injection point.
10+
*/
11+
public static boolean openVideoFullscreenPortrait(boolean original) {
12+
return Settings.OPEN_VIDEOS_FULLSCREEN_PORTRAIT.get();
13+
}
14+
}

extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/theme/ThemePatch.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ private static boolean anyEquals(int value, int... of) {
5555
/**
5656
* Injection point.
5757
*/
58-
public static boolean gradientLoadingScreenEnabled() {
58+
public static boolean gradientLoadingScreenEnabled(boolean original) {
5959
return GRADIENT_LOADING_SCREEN_ENABLED;
6060
}
6161
}

extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ public class Settings extends BaseSettings {
140140
public static final BooleanSetting PLAYBACK_SPEED_DIALOG_BUTTON = new BooleanSetting("revanced_playback_speed_dialog_button", FALSE);
141141
public static final BooleanSetting PLAYER_POPUP_PANELS = new BooleanSetting("revanced_hide_player_popup_panels", FALSE);
142142
public static final IntegerSetting PLAYER_OVERLAY_OPACITY = new IntegerSetting("revanced_player_overlay_opacity", 100, true);
143+
public static final BooleanSetting OPEN_VIDEOS_FULLSCREEN_PORTRAIT = new BooleanSetting("revanced_open_videos_fullscreen_portrait", FALSE);
143144
// Miniplayer
144145
public static final EnumSetting<MiniplayerType> MINIPLAYER_TYPE = new EnumSetting<>("revanced_miniplayer_type", MiniplayerType.ORIGINAL, true);
145146
private static final Availability MINIPLAYER_ANY_MODERN = MINIPLAYER_TYPE.availability(MODERN_1, MODERN_2, MODERN_3, MODERN_4);

patches/api/patches.api

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,10 @@ public final class app/revanced/patches/youtube/layout/player/background/PlayerC
11641164
public static final fun getPlayerControlsBackgroundPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
11651165
}
11661166

1167+
public final class app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenKt {
1168+
public static final fun getOpenVideosFullscreenPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
1169+
}
1170+
11671171
public final class app/revanced/patches/youtube/layout/player/overlay/CustomPlayerOverlayOpacityPatchKt {
11681172
public static final fun getCustomPlayerOverlayOpacityPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
11691173
}

patches/src/main/kotlin/app/revanced/patches/youtube/layout/miniplayer/MiniplayerPatch.kt

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -240,14 +240,14 @@ val miniplayerPatch = bytecodePatch(
240240
),
241241
)
242242

243-
fun MutableMethod.insertBooleanOverride(index: Int, methodName: String) {
243+
fun MutableMethod.insertMiniplayerBooleanOverride(index: Int, methodName: String) {
244244
val register = getInstruction<OneRegisterInstruction>(index).registerA
245245
addInstructions(
246246
index,
247247
"""
248-
invoke-static {v$register}, $EXTENSION_CLASS_DESCRIPTOR->$methodName(Z)Z
249-
move-result v$register
250-
""",
248+
invoke-static {v$register}, $EXTENSION_CLASS_DESCRIPTOR->$methodName(Z)Z
249+
move-result v$register
250+
"""
251251
)
252252
}
253253

@@ -257,29 +257,25 @@ val miniplayerPatch = bytecodePatch(
257257
* Adds an override to force legacy tablet miniplayer to be used or not used.
258258
*/
259259
fun MutableMethod.insertLegacyTabletMiniplayerOverride(index: Int) {
260-
insertBooleanOverride(index, "getLegacyTabletMiniplayerOverride")
260+
insertMiniplayerBooleanOverride(index, "getLegacyTabletMiniplayerOverride")
261261
}
262262

263263
/**
264264
* Adds an override to force modern miniplayer to be used or not used.
265265
*/
266266
fun MutableMethod.insertModernMiniplayerOverride(index: Int) {
267-
insertBooleanOverride(index, "getModernMiniplayerOverride")
267+
insertMiniplayerBooleanOverride(index, "getModernMiniplayerOverride")
268268
}
269269

270-
fun Fingerprint.insertLiteralValueBooleanOverride(
270+
fun Fingerprint.insertMiniplayerFeatureFlagBooleanOverride(
271271
literal: Long,
272272
extensionMethod: String,
273-
) {
274-
method.apply {
275-
val literalIndex = indexOfFirstLiteralInstructionOrThrow(literal)
276-
val targetIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT)
277-
278-
insertBooleanOverride(targetIndex + 1, extensionMethod)
279-
}
280-
}
273+
) = method.insertFeatureFlagBooleanOverride(
274+
literal,
275+
"$EXTENSION_CLASS_DESCRIPTOR->$extensionMethod(Z)Z"
276+
)
281277

282-
fun Fingerprint.insertLiteralValueFloatOverride(
278+
fun Fingerprint.insertMiniplayerFeatureFlagFloatOverride(
283279
literal: Long,
284280
extensionMethod: String,
285281
) {
@@ -370,24 +366,24 @@ val miniplayerPatch = bytecodePatch(
370366
}
371367

372368
if (is_19_23_or_greater) {
373-
miniplayerModernConstructorFingerprint.insertLiteralValueBooleanOverride(
369+
miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride(
374370
MINIPLAYER_DRAG_DROP_FEATURE_KEY,
375371
"enableMiniplayerDragAndDrop",
376372
)
377373
}
378374

379375
if (is_19_25_or_greater) {
380-
miniplayerModernConstructorFingerprint.insertLiteralValueBooleanOverride(
376+
miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride(
381377
MINIPLAYER_MODERN_FEATURE_LEGACY_KEY,
382378
"getModernMiniplayerOverride",
383379
)
384380

385-
miniplayerModernConstructorFingerprint.insertLiteralValueBooleanOverride(
381+
miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride(
386382
MINIPLAYER_MODERN_FEATURE_KEY,
387383
"getModernFeatureFlagsActiveOverride",
388384
)
389385

390-
miniplayerModernConstructorFingerprint.insertLiteralValueBooleanOverride(
386+
miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride(
391387
MINIPLAYER_DOUBLE_TAP_FEATURE_KEY,
392388
"enableMiniplayerDoubleTapAction",
393389
)
@@ -426,19 +422,19 @@ val miniplayerPatch = bytecodePatch(
426422
}
427423

428424
if (is_19_36_or_greater) {
429-
miniplayerModernConstructorFingerprint.insertLiteralValueBooleanOverride(
425+
miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride(
430426
MINIPLAYER_ROUNDED_CORNERS_FEATURE_KEY,
431427
"setRoundedCorners",
432428
)
433429
}
434430

435431
if (is_19_43_or_greater) {
436-
miniplayerOnCloseHandlerFingerprint.insertLiteralValueBooleanOverride(
432+
miniplayerOnCloseHandlerFingerprint.insertMiniplayerFeatureFlagBooleanOverride(
437433
MINIPLAYER_DISABLED_FEATURE_KEY,
438434
"getMiniplayerOnCloseHandler"
439435
)
440436

441-
miniplayerModernConstructorFingerprint.insertLiteralValueBooleanOverride(
437+
miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride(
442438
MINIPLAYER_HORIZONTAL_DRAG_FEATURE_KEY,
443439
"setHorizontalDrag",
444440
)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package app.revanced.patches.youtube.layout.player.fullscreen
2+
3+
import app.revanced.patcher.fingerprint
4+
import app.revanced.util.literal
5+
import com.android.tools.smali.dexlib2.AccessFlags
6+
7+
internal const val OPEN_VIDEOS_FULLSCREEN_PORTRAIT_FEATURE_FLAG = 45666112L
8+
9+
internal val openVideosFullscreenPortraitFingerprint = fingerprint {
10+
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
11+
returns("V")
12+
parameters("L", "Lj\$/util/Optional;")
13+
literal {
14+
OPEN_VIDEOS_FULLSCREEN_PORTRAIT_FEATURE_FLAG
15+
}
16+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package app.revanced.patches.youtube.layout.player.fullscreen
2+
3+
import app.revanced.patcher.patch.bytecodePatch
4+
import app.revanced.patches.all.misc.resources.addResources
5+
import app.revanced.patches.all.misc.resources.addResourcesPatch
6+
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
7+
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
8+
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
9+
import app.revanced.patches.youtube.misc.settings.settingsPatch
10+
import app.revanced.util.insertFeatureFlagBooleanOverride
11+
12+
private const val EXTENSION_CLASS_DESCRIPTOR =
13+
"Lapp/revanced/extension/youtube/patches/OpenVideosFullscreen;"
14+
15+
@Suppress("unused")
16+
val openVideosFullscreenPatch = bytecodePatch(
17+
name = "Open videos fullscreen",
18+
description = "Adds an option to open videos in full screen portrait mode.",
19+
) {
20+
dependsOn(
21+
sharedExtensionPatch,
22+
settingsPatch,
23+
addResourcesPatch,
24+
)
25+
26+
compatibleWith(
27+
"com.google.android.youtube"(
28+
"19.46.42",
29+
)
30+
)
31+
32+
execute {
33+
openVideosFullscreenPortraitFingerprint.method.insertFeatureFlagBooleanOverride(
34+
OPEN_VIDEOS_FULLSCREEN_PORTRAIT_FEATURE_FLAG,
35+
"$EXTENSION_CLASS_DESCRIPTOR->openVideoFullscreenPortrait(Z)Z"
36+
)
37+
38+
// Add resources and setting last, in case the user force patches an old incompatible version.
39+
40+
addResources("youtube", "layout.player.fullscreen.openVideosFullscreen")
41+
42+
PreferenceScreen.PLAYER.addPreferences(
43+
SwitchPreference("revanced_open_videos_fullscreen_portrait")
44+
)
45+
}
46+
}

patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorPatch.kt

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import app.revanced.util.getReference
2424
import app.revanced.util.indexOfFirstInstructionOrThrow
2525
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
2626
import app.revanced.util.inputStreamFromBundledResource
27+
import app.revanced.util.insertFeatureFlagBooleanOverride
2728
import com.android.tools.smali.dexlib2.Opcode
2829
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
2930
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@@ -228,19 +229,10 @@ val seekbarColorPatch = bytecodePatch(
228229

229230
// 19.25+ changes
230231

231-
playerSeekbarGradientConfigFingerprint.method.apply {
232-
val literalIndex = indexOfFirstLiteralInstructionOrThrow(PLAYER_SEEKBAR_GRADIENT_FEATURE_FLAG)
233-
val resultIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT)
234-
val register = getInstruction<OneRegisterInstruction>(resultIndex).registerA
235-
236-
addInstructions(
237-
resultIndex + 1,
238-
"""
239-
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->playerSeekbarGradientEnabled(Z)Z
240-
move-result v$register
241-
"""
242-
)
243-
}
232+
playerSeekbarGradientConfigFingerprint.method.insertFeatureFlagBooleanOverride(
233+
PLAYER_SEEKBAR_GRADIENT_FEATURE_FLAG,
234+
"$EXTENSION_CLASS_DESCRIPTOR->playerSeekbarGradientEnabled(Z)Z"
235+
)
244236

245237
lithoLinearGradientFingerprint.method.addInstruction(
246238
0,
@@ -255,19 +247,10 @@ val seekbarColorPatch = bytecodePatch(
255247
launchScreenLayoutTypeFingerprint,
256248
mainActivityOnCreateFingerprint
257249
).forEach { fingerprint ->
258-
fingerprint.method.apply {
259-
val literalIndex = indexOfFirstLiteralInstructionOrThrow(launchScreenLayoutTypeLotteFeatureFlag)
260-
val resultIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT)
261-
val register = getInstruction<OneRegisterInstruction>(resultIndex).registerA
262-
263-
addInstructions(
264-
resultIndex + 1,
265-
"""
266-
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->useLotteLaunchSplashScreen(Z)Z
267-
move-result v$register
268-
"""
269-
)
270-
}
250+
fingerprint.method.insertFeatureFlagBooleanOverride(
251+
launchScreenLayoutTypeLotteFeatureFlag,
252+
"$EXTENSION_CLASS_DESCRIPTOR->useLotteLaunchSplashScreen(Z)Z"
253+
)
271254
}
272255

273256
// Hook the splash animation drawable to set the a seekbar color theme.

patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package app.revanced.patches.youtube.layout.theme
22

33
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
4-
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
54
import app.revanced.patcher.patch.PatchException
65
import app.revanced.patcher.patch.bytecodePatch
76
import app.revanced.patcher.patch.resourcePatch
@@ -17,10 +16,7 @@ import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
1716
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
1817
import app.revanced.patches.youtube.misc.settings.settingsPatch
1918
import app.revanced.util.forEachChildElement
20-
import app.revanced.util.indexOfFirstInstructionOrThrow
21-
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
22-
import com.android.tools.smali.dexlib2.Opcode
23-
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
19+
import app.revanced.util.insertFeatureFlagBooleanOverride
2420
import org.w3c.dom.Element
2521

2622
private const val EXTENSION_CLASS_DESCRIPTOR =
@@ -212,19 +208,10 @@ val themePatch = bytecodePatch(
212208
SwitchPreference("revanced_gradient_loading_screen"),
213209
)
214210

215-
useGradientLoadingScreenFingerprint.method.apply {
216-
val literalIndex = indexOfFirstLiteralInstructionOrThrow(GRADIENT_LOADING_SCREEN_AB_CONSTANT)
217-
val isEnabledIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT)
218-
val isEnabledRegister = getInstruction<OneRegisterInstruction>(isEnabledIndex).registerA
219-
220-
addInstructions(
221-
isEnabledIndex + 1,
222-
"""
223-
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->gradientLoadingScreenEnabled()Z
224-
move-result v$isEnabledRegister
225-
""",
226-
)
227-
}
211+
useGradientLoadingScreenFingerprint.method.insertFeatureFlagBooleanOverride(
212+
GRADIENT_LOADING_SCREEN_AB_CONSTANT,
213+
"$EXTENSION_CLASS_DESCRIPTOR->gradientLoadingScreenEnabled(Z)Z"
214+
)
228215

229216
mapOf(
230217
themeHelperLightColorFingerprint to lightThemeBackgroundColor,

patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/cairo/DisableCairoSettingsPatch.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,7 @@ internal val disableCairoSettingsPatch = bytecodePatch(
3434
* <a href="https://github.com/qnblackcat/uYouPlus/issues/1468">uYouPlus#1468</a>.
3535
*/
3636
cairoFragmentConfigFingerprint.method.apply {
37-
val literalIndex = indexOfFirstLiteralInstructionOrThrow(
38-
CAIRO_CONFIG_LITERAL_VALUE,
39-
)
40-
37+
val literalIndex = indexOfFirstLiteralInstructionOrThrow(CAIRO_CONFIG_LITERAL_VALUE)
4138
val resultIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT)
4239
val register = getInstruction<OneRegisterInstruction>(resultIndex).registerA
4340

patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import app.revanced.patches.shared.misc.mapping.resourceMappings
1717
import com.android.tools.smali.dexlib2.Opcode
1818
import com.android.tools.smali.dexlib2.iface.Method
1919
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
20+
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
2021
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
2122
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
2223
import com.android.tools.smali.dexlib2.iface.reference.Reference
@@ -402,6 +403,20 @@ fun Method.findInstructionIndicesReversedOrThrow(opcode: Opcode): List<Int> {
402403
return instructions
403404
}
404405

406+
internal fun MutableMethod.insertFeatureFlagBooleanOverride(literal: Long, extensionsMethod: String) {
407+
val literalIndex = indexOfFirstLiteralInstructionOrThrow(literal)
408+
val index = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT)
409+
val register = getInstruction<OneRegisterInstruction>(index).registerA
410+
411+
addInstructions(
412+
index + 1,
413+
"""
414+
invoke-static { v$register }, $extensionsMethod
415+
move-result v$register
416+
"""
417+
)
418+
}
419+
405420
/**
406421
* Called for _all_ instructions with the given literal value.
407422
*/

patches/src/main/resources/addresources/values/strings.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
715715
<string name="revanced_hide_player_popup_panels_summary_on">Player popup panels are hidden</string>
716716
<string name="revanced_hide_player_popup_panels_summary_off">Player popup panels are shown</string>
717717
</patch>
718+
<patch id="layout.player.fullscreen.openVideosFullscreen">
719+
<string name="revanced_open_videos_fullscreen_portrait_title">Open videos in fullscreen portrait</string>
720+
<string name="revanced_open_videos_fullscreen_portrait_summary_on">Videos open fullscreen</string>
721+
<string name="revanced_open_videos_fullscreen_portrait_summary_off">Videos do not open fullscreen</string>
722+
</patch>
718723
<patch id="layout.player.overlay.customPlayerOverlayOpacityResourcePatch">
719724
<string name="revanced_player_overlay_opacity_title">Player overlay opacity</string>
720725
<string name="revanced_player_overlay_opacity_summary">Opacity value between 0-100, where 0 is transparent</string>

0 commit comments

Comments
 (0)