Compare commits
4 commits
main
...
refactor/c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d0ac9ea63 | ||
|
|
3c154e1119 | ||
|
|
2ca6f943e4 | ||
|
|
1f8a6f2040 |
35 changed files with 362 additions and 871 deletions
|
|
@ -18,7 +18,6 @@ import java.io.IOException;
|
|||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
|
|
|||
|
|
@ -2,11 +2,9 @@ package app.revanced.extension.youtube.patches;
|
|||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.*;
|
||||
import static app.revanced.extension.youtube.patches.VersionCheckPatch.*;
|
||||
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
|
@ -21,7 +19,7 @@ import app.revanced.extension.shared.Utils;
|
|||
import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings({"unused", "SpellCheckingInspection"})
|
||||
@SuppressWarnings("unused")
|
||||
public final class MiniplayerPatch {
|
||||
|
||||
/**
|
||||
|
|
@ -120,15 +118,6 @@ public final class MiniplayerPatch {
|
|||
|
||||
private static final MiniplayerType CURRENT_TYPE = Settings.MINIPLAYER_TYPE.get();
|
||||
|
||||
/**
|
||||
* Cannot turn off double tap with modern 2 or 3 with later targets,
|
||||
* as forcing it off breakings tapping the miniplayer.
|
||||
*/
|
||||
private static final boolean DOUBLE_TAP_ACTION_ENABLED =
|
||||
// 19.29+ is very broken if double tap is not enabled.
|
||||
IS_19_29_OR_GREATER ||
|
||||
(CURRENT_TYPE.isModern() && Settings.MINIPLAYER_DOUBLE_TAP_ACTION.get());
|
||||
|
||||
private static final boolean DRAG_AND_DROP_ENABLED =
|
||||
CURRENT_TYPE.isModern() && !Settings.MINIPLAYER_DISABLE_DRAG_AND_DROP.get();
|
||||
|
||||
|
|
@ -142,8 +131,7 @@ public final class MiniplayerPatch {
|
|||
|
||||
// 19.25 is last version that uses forward/back buttons for phones,
|
||||
// but buttons still show for tablets/foldable devices, and they don't work well so always hide.
|
||||
private static final boolean HIDE_REWIND_FORWARD_ENABLED = CURRENT_TYPE == MODERN_1
|
||||
&& (VersionCheckPatch.IS_19_34_OR_GREATER || Settings.MINIPLAYER_HIDE_REWIND_FORWARD.get());
|
||||
private static final boolean HIDE_REWIND_FORWARD_ENABLED = CURRENT_TYPE == MODERN_1;
|
||||
|
||||
private static final boolean MINIPLAYER_ROUNDED_CORNERS_ENABLED =
|
||||
CURRENT_TYPE.isModern() && !Settings.MINIPLAYER_DISABLE_ROUNDED_CORNERS.get();
|
||||
|
|
@ -151,13 +139,6 @@ public final class MiniplayerPatch {
|
|||
private static final boolean MINIPLAYER_HORIZONTAL_DRAG_ENABLED =
|
||||
DRAG_AND_DROP_ENABLED && !Settings.MINIPLAYER_DISABLE_HORIZONTAL_DRAG.get();
|
||||
|
||||
/**
|
||||
* Remove a broken and always present subtitle text that is only
|
||||
* present with {@link MiniplayerType#MODERN_2}. Bug was fixed in 19.21.
|
||||
*/
|
||||
private static final boolean HIDE_BROKEN_MODERN_2_SUBTITLE =
|
||||
CURRENT_TYPE == MODERN_2 && !IS_19_21_OR_GREATER;
|
||||
|
||||
private static final int OPACITY_LEVEL;
|
||||
|
||||
static {
|
||||
|
|
@ -190,11 +171,7 @@ public final class MiniplayerPatch {
|
|||
@Override
|
||||
public boolean isAvailable() {
|
||||
MiniplayerType type = Settings.MINIPLAYER_TYPE.get();
|
||||
return type == MODERN_4
|
||||
|| (!IS_19_20_OR_GREATER && (type == MODERN_1 || type == MODERN_3))
|
||||
|| (!IS_19_26_OR_GREATER && type == MODERN_1
|
||||
&& !Settings.MINIPLAYER_DOUBLE_TAP_ACTION.get() && Settings.MINIPLAYER_DISABLE_DRAG_AND_DROP.get())
|
||||
|| (IS_19_29_OR_GREATER && type == MODERN_3);
|
||||
return type == MODERN_4 || type == MODERN_3;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -325,7 +302,7 @@ public final class MiniplayerPatch {
|
|||
return original;
|
||||
}
|
||||
|
||||
return DOUBLE_TAP_ACTION_ENABLED;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -435,25 +412,4 @@ public final class MiniplayerPatch {
|
|||
Logger.printException(() -> "hideMiniplayerSubTexts failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void playerOverlayGroupCreated(View group) {
|
||||
try {
|
||||
if (HIDE_BROKEN_MODERN_2_SUBTITLE && MODERN_OVERLAY_SUBTITLE_TEXT != 0) {
|
||||
if (group instanceof ViewGroup) {
|
||||
View subtitleText = Utils.getChildView((ViewGroup) group, true,
|
||||
view -> view.getId() == MODERN_OVERLAY_SUBTITLE_TEXT);
|
||||
|
||||
if (subtitleText != null) {
|
||||
subtitleText.setVisibility(View.GONE);
|
||||
Logger.printDebug(() -> "Modern overlay subtitle view set to hidden");
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "playerOverlayGroupCreated failure", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,13 +81,6 @@ public class ShortsAutoplayPatch {
|
|||
final boolean autoplay;
|
||||
|
||||
if (isAppInBackgroundPiPMode()) {
|
||||
if (!VersionCheckPatch.IS_19_34_OR_GREATER) {
|
||||
// 19.34+ is required to set background play behavior.
|
||||
Logger.printDebug(() -> "PiP Shorts not supported, using original repeat behavior");
|
||||
|
||||
return original;
|
||||
}
|
||||
|
||||
autoplay = Settings.SHORTS_AUTOPLAY_BACKGROUND.get();
|
||||
} else {
|
||||
autoplay = Settings.SHORTS_AUTOPLAY.get();
|
||||
|
|
|
|||
|
|
@ -7,19 +7,6 @@ public class VersionCheckPatch {
|
|||
return Utils.getAppVersionName().compareTo(version) >= 0;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static final boolean IS_19_17_OR_GREATER = isVersionOrGreater("19.17.00");
|
||||
@Deprecated
|
||||
public static final boolean IS_19_20_OR_GREATER = isVersionOrGreater("19.20.00");
|
||||
@Deprecated
|
||||
public static final boolean IS_19_21_OR_GREATER = isVersionOrGreater("19.21.00");
|
||||
@Deprecated
|
||||
public static final boolean IS_19_26_OR_GREATER = isVersionOrGreater("19.26.00");
|
||||
@Deprecated
|
||||
public static final boolean IS_19_29_OR_GREATER = isVersionOrGreater("19.29.00");
|
||||
@Deprecated
|
||||
public static final boolean IS_19_34_OR_GREATER = isVersionOrGreater("19.34.00");
|
||||
|
||||
public static final boolean IS_20_21_OR_GREATER = isVersionOrGreater("20.21.00");
|
||||
|
||||
public static final boolean IS_20_22_OR_GREATER = isVersionOrGreater("20.22.00");
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
package app.revanced.extension.youtube.patches.litho;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import app.revanced.extension.shared.patches.litho.FilterGroupList.ByteArrayFilt
|
|||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
|
||||
import app.revanced.extension.youtube.patches.VersionCheckPatch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.ShortsPlayerState;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import androidx.annotation.Nullable;
|
|||
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
|
||||
/**
|
||||
* Dynamic drawable that is either the regular or bolded ReVanced preference icon.
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import java.util.Arrays;
|
|||
import java.util.Scanner;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.ResourceType;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import app.revanced.extension.shared.ResourceType;
|
|||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseActivityHook;
|
||||
import app.revanced.extension.youtube.patches.VersionCheckPatch;
|
||||
import app.revanced.extension.youtube.patches.spoof.SpoofAppVersionPatch;
|
||||
import app.revanced.extension.youtube.settings.preference.YouTubePreferenceFragment;
|
||||
import app.revanced.extension.youtube.settings.search.YouTubeSearchViewController;
|
||||
|
||||
|
|
@ -19,7 +18,7 @@ import app.revanced.extension.youtube.settings.search.YouTubeSearchViewControlle
|
|||
* Hooks LicenseActivity to inject a custom {@link YouTubePreferenceFragment}
|
||||
* with a toolbar and search functionality.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
|
||||
public class YouTubeActivityHook extends BaseActivityHook {
|
||||
|
||||
/**
|
||||
|
|
@ -121,17 +120,9 @@ public class YouTubeActivityHook extends BaseActivityHook {
|
|||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static boolean useCairoSettingsFragment(boolean original) {
|
||||
// Early targets have layout issues and it's better to always force off.
|
||||
if (!VersionCheckPatch.IS_19_34_OR_GREATER) {
|
||||
return false;
|
||||
}
|
||||
if (Settings.RESTORE_OLD_SETTINGS_MENUS.get()) {
|
||||
return false;
|
||||
}
|
||||
// Spoofing can cause half broken settings menus of old and new settings.
|
||||
if (SpoofAppVersionPatch.isSpoofingToLessThan("19.35.36")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// On the first launch of a clean install, forcing the cairo menu can give a
|
||||
// half broken appearance because all the preference icons may not be available yet.
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ import app.revanced.extension.shared.settings.Setting;
|
|||
import app.revanced.extension.shared.settings.preference.CustomDialogListPreference;
|
||||
import app.revanced.extension.shared.settings.preference.ResettableEditTextPreference;
|
||||
import app.revanced.extension.shared.ui.CustomDialog;
|
||||
import app.revanced.extension.shared.ui.Dim;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.sponsorblock.SegmentPlaybackController;
|
||||
import app.revanced.extension.youtube.sponsorblock.SponsorBlockSettings;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import app.revanced.patches.youtube.misc.engagement.addEngagementPanelIdHook
|
|||
import app.revanced.patches.youtube.misc.engagement.engagementPanelHookPatch
|
||||
import app.revanced.patches.youtube.misc.fix.backtoexitgesture.fixBackToExitGesturePatch
|
||||
import app.revanced.patches.youtube.misc.litho.filter.lithoFilterPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_14_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
|
|
@ -153,20 +152,17 @@ val hideAdsPatch = bytecodePatch(
|
|||
|
||||
// Hide player overlay view. This can be hidden with a regular litho filter
|
||||
// but an empty space remains.
|
||||
if (is_20_14_or_greater) {
|
||||
playerOverlayTimelyShelfMethod.addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static {}, ${EXTENSION_CLASS_DESCRIPTOR}->hideAds()Z
|
||||
move-result v0
|
||||
if-eqz v0, :show
|
||||
return-void
|
||||
:show
|
||||
nop
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
playerOverlayTimelyShelfMethod.addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static {}, ${EXTENSION_CLASS_DESCRIPTOR}->hideAds()Z
|
||||
move-result v0
|
||||
if-eqz v0, :show
|
||||
return-void
|
||||
:show
|
||||
nop
|
||||
"""
|
||||
)
|
||||
|
||||
// Hide end screen store banner.
|
||||
|
||||
|
|
|
|||
|
|
@ -7,13 +7,11 @@ 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.playservice.is_20_14_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import java.util.logging.Logger
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/DisableDoubleTapActionsPatch;"
|
||||
|
|
@ -42,15 +40,6 @@ val disableDoubleTapActionsPatch = bytecodePatch(
|
|||
)
|
||||
|
||||
apply {
|
||||
if (!is_20_14_or_greater) {
|
||||
// Show a message if users have version constrain off and are patching the oldest version,
|
||||
// just to prevent spamming a cryptic error message the user may not understand
|
||||
// and don't add in app settings that won't work.
|
||||
return@apply Logger.getLogger(this::class.java.name).warning(
|
||||
"Disable double tap actions requires 20.14.43+",
|
||||
)
|
||||
}
|
||||
|
||||
addResources("youtube", "interaction.doubletap.disableDoubleTapActionsPatch")
|
||||
|
||||
PreferenceScreen.PLAYER.addPreferences(
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ 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.playservice.is_19_17_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
|
|
@ -73,35 +72,18 @@ val enableSlideToSeekPatch = bytecodePatch(
|
|||
if (!modifiedMethods) throw PatchException("Could not find methods to modify")
|
||||
|
||||
// Disable the double speed seek gesture.
|
||||
if (is_19_17_or_greater) {
|
||||
disableFastForwardGestureMethodMatch.let {
|
||||
it.method.apply {
|
||||
val targetIndex = it[-1]
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
disableFastForwardGestureMethodMatch.let {
|
||||
it.method.apply {
|
||||
val targetIndex = it[-1]
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
targetIndex + 1,
|
||||
"""
|
||||
invoke-static { v$targetRegister }, $extensionMethodDescriptor
|
||||
move-result v$targetRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
disableFastForwardLegacyMethodMatch.let {
|
||||
it.method.apply {
|
||||
val insertIndex = it[-1] + 1
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static { v$targetRegister }, $extensionMethodDescriptor
|
||||
move-result v$targetRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
addInstructions(
|
||||
targetIndex + 1,
|
||||
"""
|
||||
invoke-static { v$targetRegister }, $extensionMethodDescriptor
|
||||
move-result v$targetRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
|||
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_43_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_22_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
|
|
@ -39,7 +38,7 @@ private val swipeControlsResourcePatch = resourcePatch {
|
|||
// If fullscreen swipe is enabled in newer versions the app can crash.
|
||||
// It likely is caused by conflicting experimental flags that are never enabled together.
|
||||
// Flag was completely removed in 20.34+
|
||||
if (is_19_43_or_greater && !is_20_22_or_greater) {
|
||||
if (!is_20_22_or_greater) {
|
||||
PreferenceScreen.SWIPE_CONTROLS.addPreferences(
|
||||
SwitchPreference("revanced_swipe_change_video"),
|
||||
)
|
||||
|
|
@ -140,7 +139,7 @@ val swipeControlsPatch = bytecodePatch(
|
|||
|
||||
// region patch to enable/disable swipe to change video.
|
||||
|
||||
if (is_19_43_or_greater && !is_20_34_or_greater) {
|
||||
if (!is_20_34_or_greater) {
|
||||
swipeChangeVideoMethodMatch.let {
|
||||
it.method.insertLiteralOverride(
|
||||
it[-1],
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import app.revanced.patches.youtube.misc.contexthook.hookClientContextPatch
|
|||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.navigation.hookNavigationButtonCreated
|
||||
import app.revanced.patches.youtube.misc.navigation.navigationBarHookPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_15_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_31_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
|
|
@ -78,17 +77,15 @@ val navigationBarPatch = bytecodePatch(
|
|||
SwitchPreference("revanced_narrow_navigation_buttons"),
|
||||
)
|
||||
|
||||
if (is_19_25_or_greater) {
|
||||
preferences += SwitchPreference("revanced_disable_translucent_navigation_bar_light")
|
||||
preferences += SwitchPreference("revanced_disable_translucent_navigation_bar_dark")
|
||||
preferences += SwitchPreference("revanced_disable_translucent_navigation_bar_light")
|
||||
preferences += SwitchPreference("revanced_disable_translucent_navigation_bar_dark")
|
||||
|
||||
PreferenceScreen.GENERAL.addPreferences(
|
||||
SwitchPreference("revanced_disable_translucent_status_bar")
|
||||
)
|
||||
PreferenceScreen.GENERAL.addPreferences(
|
||||
SwitchPreference("revanced_disable_translucent_status_bar")
|
||||
)
|
||||
|
||||
if (is_20_15_or_greater) {
|
||||
preferences += SwitchPreference("revanced_navigation_bar_animations")
|
||||
}
|
||||
if (is_20_15_or_greater) {
|
||||
preferences += SwitchPreference("revanced_navigation_bar_animations")
|
||||
}
|
||||
|
||||
PreferenceScreen.GENERAL.addPreferences(
|
||||
|
|
@ -124,27 +121,25 @@ val navigationBarPatch = bytecodePatch(
|
|||
hookNavigationButtonCreated(EXTENSION_CLASS_DESCRIPTOR)
|
||||
|
||||
// Force on/off translucent effect on status bar and navigation buttons.
|
||||
if (is_19_25_or_greater) {
|
||||
translucentNavigationStatusBarFeatureFlagMethodMatch.let {
|
||||
it.method.insertLiteralOverride(
|
||||
it[0],
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationStatusBar(Z)Z",
|
||||
)
|
||||
}
|
||||
translucentNavigationStatusBarFeatureFlagMethodMatch.let {
|
||||
it.method.insertLiteralOverride(
|
||||
it[0],
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationStatusBar(Z)Z",
|
||||
)
|
||||
}
|
||||
|
||||
translucentNavigationButtonsFeatureFlagMethodMatch.let {
|
||||
it.method.insertLiteralOverride(
|
||||
it[0],
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationButtons(Z)Z",
|
||||
)
|
||||
}
|
||||
translucentNavigationButtonsFeatureFlagMethodMatch.let {
|
||||
it.method.insertLiteralOverride(
|
||||
it[0],
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationButtons(Z)Z",
|
||||
)
|
||||
}
|
||||
|
||||
translucentNavigationButtonsSystemFeatureFlagMethodMatch.let {
|
||||
it.method.insertLiteralOverride(
|
||||
it[0],
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationButtons(Z)Z",
|
||||
)
|
||||
}
|
||||
translucentNavigationButtonsSystemFeatureFlagMethodMatch.let {
|
||||
it.method.insertLiteralOverride(
|
||||
it[0],
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationButtons(Z)Z",
|
||||
)
|
||||
}
|
||||
|
||||
if (is_20_15_or_greater) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package app.revanced.patches.youtube.layout.hide.endscreencards
|
|||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.extensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.immutableClassDef
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
|
|
@ -12,7 +11,6 @@ import app.revanced.patches.shared.misc.mapping.ResourceType
|
|||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_43_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
|
|
@ -90,18 +88,16 @@ val hideEndScreenCardsPatch = bytecodePatch(
|
|||
}
|
||||
}
|
||||
|
||||
if (is_19_43_or_greater) {
|
||||
showEndscreenCardsMethod.addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->hideEndScreenCards()Z
|
||||
move-result v0
|
||||
if-eqz v0, :show
|
||||
return-void
|
||||
:show
|
||||
nop
|
||||
""",
|
||||
)
|
||||
}
|
||||
showEndscreenCardsMethod.addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->hideEndScreenCards()Z
|
||||
move-result v0
|
||||
if-eqz v0, :show
|
||||
return-void
|
||||
:show
|
||||
nop
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -256,15 +256,12 @@ val hideShortsComponentsPatch = bytecodePatch(
|
|||
}
|
||||
|
||||
// Hook to hide the shared navigation bar when the Shorts player is opened.
|
||||
(
|
||||
if (is_20_45_or_greater) {
|
||||
renderBottomNavigationBarParentMethod
|
||||
} else if (is_19_41_or_greater) {
|
||||
renderBottomNavigationBarLegacy1941ParentMethod
|
||||
} else {
|
||||
legacyRenderBottomNavigationBarLegacyParentMethod
|
||||
}
|
||||
).immutableClassDef.getRenderBottomNavigationBarMethodMatch().addInstruction(
|
||||
|
||||
if (is_20_45_or_greater) {
|
||||
renderBottomNavigationBarParentMethod
|
||||
} else {
|
||||
renderBottomNavigationBarLegacy1941ParentMethod
|
||||
}.immutableClassDef.getRenderBottomNavigationBarMethodMatch().addInstruction(
|
||||
0,
|
||||
"invoke-static { p1 }, $FILTER_CLASS_DESCRIPTOR->hideNavigationBar(Ljava/lang/String;)V",
|
||||
)
|
||||
|
|
@ -292,20 +289,19 @@ val hideShortsComponentsPatch = bytecodePatch(
|
|||
// Flags might be present in earlier targets, but they are not found in 19.47.53.
|
||||
// If these flags are forced on, the experimental layout is still not used, and
|
||||
// it appears the features requires additional server side data to fully use.
|
||||
if (is_20_07_or_greater) {
|
||||
// Experimental Shorts player uses Android native buttons and not Litho,
|
||||
// and the layout is provided by the server.
|
||||
//
|
||||
// Since the buttons are native components and not Litho, it should be possible to
|
||||
// fix the RYD Shorts loading delay by asynchronously loading RYD and updating
|
||||
// the button text after RYD has loaded.
|
||||
shortsExperimentalPlayerFeatureFlagMethod.returnLate(false)
|
||||
|
||||
// Experimental UI renderer must also be disabled since it requires the
|
||||
// experimental Shorts player. If this is enabled but Shorts player
|
||||
// is disabled then the app crashes when the Shorts player is opened.
|
||||
renderNextUIFeatureFlagMethod.returnLate(false)
|
||||
}
|
||||
// Experimental Shorts player uses Android native buttons and not Litho,
|
||||
// and the layout is provided by the server.
|
||||
//
|
||||
// Since the buttons are native components and not Litho, it should be possible to
|
||||
// fix the RYD Shorts loading delay by asynchronously loading RYD and updating
|
||||
// the button text after RYD has loaded.
|
||||
shortsExperimentalPlayerFeatureFlagMethod.returnLate(false)
|
||||
|
||||
// Experimental UI renderer must also be disabled since it requires the
|
||||
// experimental Shorts player. If this is enabled but Shorts player
|
||||
// is disabled then the app crashes when the Shorts player is opened.
|
||||
renderNextUIFeatureFlagMethod.returnLate(false)
|
||||
|
||||
// endregion
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
package app.revanced.patches.youtube.layout.miniplayer
|
||||
|
||||
import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethod
|
||||
import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patcher.classDef
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
|
|
@ -24,19 +23,13 @@ import app.revanced.patches.youtube.misc.settings.settingsPatch
|
|||
import app.revanced.util.*
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
||||
import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||
|
||||
// Only available in 19.15 and upwards.
|
||||
internal var ytOutlineXWhite24 = -1L
|
||||
private set
|
||||
internal var ytOutlinePictureInPictureWhite24 = -1L
|
||||
private set
|
||||
|
||||
|
|
@ -50,13 +43,6 @@ private val miniplayerResourcePatch = resourcePatch {
|
|||
// Resource id is not used during patching, but is used by extension.
|
||||
// Verify the resource is present while patching.
|
||||
ResourceType.ID["modern_miniplayer_subtitle_text"]
|
||||
|
||||
// Only required for exactly 19.16
|
||||
if (!is_19_17_or_greater) {
|
||||
ytOutlinePictureInPictureWhite24 =
|
||||
ResourceType.DRAWABLE["yt_outline_picture_in_picture_white_24"]
|
||||
ytOutlineXWhite24 = ResourceType.DRAWABLE["yt_outline_x_white_24"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -94,64 +80,24 @@ val miniplayerPatch = bytecodePatch(
|
|||
preferences +=
|
||||
if (is_20_37_or_greater) {
|
||||
ListPreference("revanced_miniplayer_type")
|
||||
} else if (is_20_03_or_greater) {
|
||||
} else {
|
||||
ListPreference(
|
||||
key = "revanced_miniplayer_type",
|
||||
entriesKey = "revanced_miniplayer_type_legacy_20_03_entries",
|
||||
entryValuesKey = "revanced_miniplayer_type_legacy_20_03_entry_values",
|
||||
)
|
||||
} else if (is_19_43_or_greater) {
|
||||
ListPreference(
|
||||
key = "revanced_miniplayer_type",
|
||||
entriesKey = "revanced_miniplayer_type_legacy_19_43_entries",
|
||||
entryValuesKey = "revanced_miniplayer_type_legacy_19_43_entry_values",
|
||||
)
|
||||
} else {
|
||||
ListPreference(
|
||||
key = "revanced_miniplayer_type",
|
||||
entriesKey = "revanced_miniplayer_type_legacy_19_16_entries",
|
||||
entryValuesKey = "revanced_miniplayer_type_legacy_19_16_entry_values",
|
||||
)
|
||||
}
|
||||
|
||||
if (is_19_25_or_greater) {
|
||||
if (!is_19_29_or_greater) {
|
||||
preferences += SwitchPreference("revanced_miniplayer_double_tap_action")
|
||||
}
|
||||
preferences += SwitchPreference("revanced_miniplayer_disable_drag_and_drop")
|
||||
}
|
||||
|
||||
if (is_19_43_or_greater) {
|
||||
preferences += SwitchPreference("revanced_miniplayer_disable_horizontal_drag")
|
||||
}
|
||||
|
||||
if (is_19_36_or_greater) {
|
||||
preferences += SwitchPreference("revanced_miniplayer_disable_rounded_corners")
|
||||
}
|
||||
|
||||
preferences += SwitchPreference("revanced_miniplayer_disable_drag_and_drop")
|
||||
preferences += SwitchPreference("revanced_miniplayer_disable_horizontal_drag")
|
||||
preferences += SwitchPreference("revanced_miniplayer_disable_rounded_corners")
|
||||
preferences += SwitchPreference("revanced_miniplayer_hide_subtext")
|
||||
preferences += SwitchPreference("revanced_miniplayer_hide_overlay_buttons")
|
||||
|
||||
preferences += if (is_19_26_or_greater) {
|
||||
SwitchPreference("revanced_miniplayer_hide_overlay_buttons")
|
||||
} else {
|
||||
SwitchPreference(
|
||||
key = "revanced_miniplayer_hide_overlay_buttons",
|
||||
titleKey = "revanced_miniplayer_hide_overlay_buttons_legacy_title",
|
||||
summaryOnKey = "revanced_miniplayer_hide_overlay_buttons_legacy_summary_on",
|
||||
summaryOffKey = "revanced_miniplayer_hide_overlay_buttons_legacy_summary_off",
|
||||
)
|
||||
}
|
||||
|
||||
if (!is_19_26_or_greater) {
|
||||
preferences += SwitchPreference("revanced_miniplayer_hide_rewind_forward")
|
||||
}
|
||||
|
||||
if (is_19_26_or_greater) {
|
||||
preferences += TextPreference(
|
||||
"revanced_miniplayer_width_dip",
|
||||
inputType = InputType.NUMBER
|
||||
)
|
||||
}
|
||||
preferences += TextPreference(
|
||||
"revanced_miniplayer_width_dip",
|
||||
inputType = InputType.NUMBER
|
||||
)
|
||||
|
||||
preferences += TextPreference("revanced_miniplayer_opacity", inputType = InputType.NUMBER)
|
||||
|
||||
|
|
@ -283,109 +229,74 @@ val miniplayerPatch = bytecodePatch(
|
|||
}
|
||||
}
|
||||
|
||||
if (is_19_23_or_greater) {
|
||||
miniplayerModernConstructorMethod.insertMiniplayerFeatureFlagBooleanOverride(
|
||||
MINIPLAYER_DRAG_DROP_FEATURE_KEY,
|
||||
"getMiniplayerDragAndDrop",
|
||||
miniplayerModernConstructorMethod.insertMiniplayerFeatureFlagBooleanOverride(
|
||||
MINIPLAYER_DRAG_DROP_FEATURE_KEY,
|
||||
"getMiniplayerDragAndDrop",
|
||||
)
|
||||
|
||||
miniplayerModernConstructorMethod.insertMiniplayerFeatureFlagBooleanOverride(
|
||||
MINIPLAYER_MODERN_FEATURE_LEGACY_KEY,
|
||||
"getModernMiniplayerOverride",
|
||||
)
|
||||
|
||||
miniplayerModernConstructorMethod.insertMiniplayerFeatureFlagBooleanOverride(
|
||||
MINIPLAYER_MODERN_FEATURE_KEY,
|
||||
"getModernFeatureFlagsActiveOverride",
|
||||
)
|
||||
|
||||
miniplayerModernConstructorMethod.insertMiniplayerFeatureFlagBooleanOverride(
|
||||
MINIPLAYER_DOUBLE_TAP_FEATURE_KEY,
|
||||
"getMiniplayerDoubleTapAction",
|
||||
)
|
||||
|
||||
miniplayerModernConstructorMethod.apply {
|
||||
val literalIndex = indexOfFirstLiteralInstructionOrThrow(
|
||||
MINIPLAYER_INITIAL_SIZE_FEATURE_KEY,
|
||||
)
|
||||
val targetIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.LONG_TO_INT)
|
||||
val register = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
targetIndex + 1,
|
||||
"""
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getMiniplayerDefaultSize(I)I
|
||||
move-result v$register
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
if (is_19_25_or_greater) {
|
||||
miniplayerModernConstructorMethod.insertMiniplayerFeatureFlagBooleanOverride(
|
||||
MINIPLAYER_MODERN_FEATURE_LEGACY_KEY,
|
||||
"getModernMiniplayerOverride",
|
||||
)
|
||||
// Override a minimum size constant.
|
||||
miniplayerMinimumSizeMethodMatch.let {
|
||||
it.method.apply {
|
||||
val index = it[1]
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
miniplayerModernConstructorMethod.insertMiniplayerFeatureFlagBooleanOverride(
|
||||
MINIPLAYER_MODERN_FEATURE_KEY,
|
||||
"getModernFeatureFlagsActiveOverride",
|
||||
)
|
||||
|
||||
miniplayerModernConstructorMethod.insertMiniplayerFeatureFlagBooleanOverride(
|
||||
MINIPLAYER_DOUBLE_TAP_FEATURE_KEY,
|
||||
"getMiniplayerDoubleTapAction",
|
||||
)
|
||||
}
|
||||
|
||||
if (is_19_26_or_greater) {
|
||||
miniplayerModernConstructorMethod.apply {
|
||||
val literalIndex = indexOfFirstLiteralInstructionOrThrow(
|
||||
MINIPLAYER_INITIAL_SIZE_FEATURE_KEY,
|
||||
)
|
||||
val targetIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.LONG_TO_INT)
|
||||
val register = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
targetIndex + 1,
|
||||
"""
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getMiniplayerDefaultSize(I)I
|
||||
move-result v$register
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
// Override a minimum size constant.
|
||||
miniplayerMinimumSizeMethodMatch.let {
|
||||
it.method.apply {
|
||||
val index = it[1]
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
// Smaller sizes can be used, but the miniplayer will always start in size 170 if set any smaller.
|
||||
// The 170 initial limit probably could be patched to allow even smaller initial sizes,
|
||||
// but 170 is already half the horizontal space and smaller does not seem useful.
|
||||
replaceInstruction(index, "const/16 v$register, 170")
|
||||
}
|
||||
// Smaller sizes can be used, but the miniplayer will always start in size 170 if set any smaller.
|
||||
// The 170 initial limit probably could be patched to allow even smaller initial sizes,
|
||||
// but 170 is already half the horizontal space and smaller does not seem useful.
|
||||
replaceInstruction(index, "const/16 v$register, 170")
|
||||
}
|
||||
}
|
||||
|
||||
if (is_19_36_or_greater) {
|
||||
miniplayerModernConstructorMethod.insertMiniplayerFeatureFlagBooleanOverride(
|
||||
MINIPLAYER_ROUNDED_CORNERS_FEATURE_KEY,
|
||||
"getRoundedCorners",
|
||||
)
|
||||
}
|
||||
miniplayerModernConstructorMethod.insertMiniplayerFeatureFlagBooleanOverride(
|
||||
MINIPLAYER_ROUNDED_CORNERS_FEATURE_KEY,
|
||||
"getRoundedCorners",
|
||||
)
|
||||
|
||||
if (is_19_43_or_greater) {
|
||||
miniplayerOnCloseHandlerMethod.insertMiniplayerFeatureFlagBooleanOverride(
|
||||
MINIPLAYER_DISABLED_FEATURE_KEY,
|
||||
"getMiniplayerOnCloseHandler",
|
||||
)
|
||||
miniplayerOnCloseHandlerMethod.insertMiniplayerFeatureFlagBooleanOverride(
|
||||
MINIPLAYER_DISABLED_FEATURE_KEY,
|
||||
"getMiniplayerOnCloseHandler",
|
||||
)
|
||||
|
||||
miniplayerModernConstructorMethod.insertMiniplayerFeatureFlagBooleanOverride(
|
||||
MINIPLAYER_HORIZONTAL_DRAG_FEATURE_KEY,
|
||||
"getHorizontalDrag",
|
||||
)
|
||||
miniplayerModernConstructorMethod.insertMiniplayerFeatureFlagBooleanOverride(
|
||||
MINIPLAYER_HORIZONTAL_DRAG_FEATURE_KEY,
|
||||
"getHorizontalDrag",
|
||||
)
|
||||
|
||||
miniplayerModernConstructorMethod.insertMiniplayerFeatureFlagBooleanOverride(
|
||||
MINIPLAYER_ANIMATED_EXPAND_FEATURE_KEY,
|
||||
"getMaximizeAnimation",
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Fix 19.16 using mixed up drawables for tablet modern.
|
||||
// YT fixed this mistake in 19.17.
|
||||
// Fix this, by swapping the drawable resource values with each other.
|
||||
if (!is_19_17_or_greater) {
|
||||
miniplayerModernViewParentMethod.immutableClassDef.getMiniplayerModernExpandCloseDrawablesMethod()
|
||||
.apply {
|
||||
listOf(
|
||||
ytOutlinePictureInPictureWhite24 to ytOutlineXWhite24,
|
||||
ytOutlineXWhite24 to ytOutlinePictureInPictureWhite24,
|
||||
).forEach { (originalResource, replacementResource) ->
|
||||
val imageResourceIndex =
|
||||
indexOfFirstLiteralInstructionOrThrow(originalResource)
|
||||
val register =
|
||||
getInstruction<OneRegisterInstruction>(imageResourceIndex).registerA
|
||||
|
||||
replaceInstruction(
|
||||
imageResourceIndex,
|
||||
"const v$register, $replacementResource"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
miniplayerModernConstructorMethod.insertMiniplayerFeatureFlagBooleanOverride(
|
||||
MINIPLAYER_ANIMATED_EXPAND_FEATURE_KEY,
|
||||
"getMaximizeAnimation",
|
||||
)
|
||||
|
||||
// endregion
|
||||
|
||||
|
|
@ -443,45 +354,6 @@ val miniplayerPatch = bytecodePatch(
|
|||
"hideMiniplayerSubTexts(Landroid/view/View;)V",
|
||||
)
|
||||
|
||||
// Modern 2 has a broken overlay subtitle view that is always present.
|
||||
// Modern 2 uses the same overlay controls as the regular video player,
|
||||
// and the overlay views are added at runtime.
|
||||
// Add a hook to the overlay class, and pass the added views to extension.
|
||||
// Problem is fixed in 19.21+
|
||||
//
|
||||
// NOTE: Modern 2 uses the same video UI as the regular player except resized to smaller.
|
||||
// This patch code could be used to hide other player overlays that do not use Litho.
|
||||
if (!is_19_17_or_greater) {
|
||||
playerOverlaysLayoutMethod.classDef.methods.add(
|
||||
ImmutableMethod(
|
||||
YOUTUBE_PLAYER_OVERLAYS_LAYOUT_CLASS_NAME,
|
||||
"addView",
|
||||
listOf(
|
||||
ImmutableMethodParameter("Landroid/view/View;", null, null),
|
||||
ImmutableMethodParameter("I", null, null),
|
||||
ImmutableMethodParameter(
|
||||
"Landroid/view/ViewGroup\$LayoutParams;",
|
||||
null,
|
||||
null,
|
||||
),
|
||||
),
|
||||
"V",
|
||||
AccessFlags.PUBLIC.value,
|
||||
null,
|
||||
null,
|
||||
MutableMethodImplementation(4),
|
||||
).toMutable().apply {
|
||||
addInstructions(
|
||||
"""
|
||||
invoke-super { p0, p1, p2, p3 }, Landroid/view/ViewGroup;->addView(Landroid/view/View;ILandroid/view/ViewGroup${'$'}LayoutParams;)V
|
||||
invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->playerOverlayGroupCreated(Landroid/view/View;)V
|
||||
return-void
|
||||
""",
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
package app.revanced.patches.youtube.layout.player.fullscreen
|
||||
|
||||
import app.revanced.patcher.CompositeMatch
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.youtube.layout.shortsplayer.openShortsInRegularPlayerPatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_46_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.util.insertLiteralOverride
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
|
@ -25,26 +23,18 @@ internal val openVideosFullscreenHookPatch = bytecodePatch {
|
|||
)
|
||||
|
||||
apply {
|
||||
var match: CompositeMatch
|
||||
var insertIndex: Int
|
||||
val match = openVideosFullscreenPortraitMethodMatch
|
||||
val insertIndex = match[0]
|
||||
|
||||
if (is_19_46_or_greater) {
|
||||
match = openVideosFullscreenPortraitMethodMatch
|
||||
insertIndex = match[0]
|
||||
|
||||
openVideosFullscreenPortraitMethodMatch.let {
|
||||
// Remove A/B feature call that forces what this patch already does.
|
||||
// Cannot use the A/B flag to accomplish the same goal because 19.50+
|
||||
// Shorts fullscreen regular player does not use fullscreen
|
||||
// if the player is minimized, and it must be forced using other conditional check.
|
||||
it.method.insertLiteralOverride(
|
||||
it[-1],
|
||||
false,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
match = openVideosFullscreenPortraitLegacyMethodMatch
|
||||
insertIndex = match[-1]
|
||||
match.let {
|
||||
// Remove A/B feature call that forces what this patch already does.
|
||||
// Cannot use the A/B flag to accomplish the same goal because 19.50+
|
||||
// Shorts fullscreen regular player does not use fullscreen
|
||||
// if the player is minimized, and it must be forced using other conditional check.
|
||||
it.method.insertLiteralOverride(
|
||||
it[-1],
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
match.method.apply {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR =
|
|||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/litho/ReturnYouTubeDislikeFilter;"
|
||||
|
||||
@Suppress("ObjectPropertyName")
|
||||
@Suppress("unused")
|
||||
val returnYouTubeDislikePatch = bytecodePatch(
|
||||
name = "Return YouTube Dislike",
|
||||
description = "Adds an option to show the dislike count of videos with Return YouTube Dislike.",
|
||||
|
|
@ -146,36 +146,18 @@ val returnYouTubeDislikePatch = bytecodePatch(
|
|||
// Find the instruction for creating the text data object.
|
||||
val textDataClassType = textComponentDataMethod.immutableClassDef.type
|
||||
|
||||
val insertIndex: Int
|
||||
val charSequenceRegister: Int
|
||||
|
||||
if (is_19_33_or_greater && !is_20_10_or_greater) {
|
||||
val index = indexOfFirstInstructionOrThrow {
|
||||
(opcode == Opcode.INVOKE_STATIC || opcode == Opcode.INVOKE_STATIC_RANGE) &&
|
||||
methodReference?.returnType == textDataClassType
|
||||
}
|
||||
|
||||
insertIndex = indexOfFirstInstructionOrThrow(index) {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
methodReference?.parameterTypes?.firstOrNull() == "Ljava/lang/CharSequence;"
|
||||
}
|
||||
|
||||
charSequenceRegister =
|
||||
getInstruction<FiveRegisterInstruction>(insertIndex).registerD
|
||||
} else {
|
||||
insertIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.NEW_INSTANCE &&
|
||||
typeReference?.type == textDataClassType
|
||||
}
|
||||
|
||||
val charSequenceIndex = indexOfFirstInstructionOrThrow(insertIndex) {
|
||||
opcode == Opcode.IPUT_OBJECT &&
|
||||
fieldReference?.type == "Ljava/lang/CharSequence;"
|
||||
}
|
||||
charSequenceRegister =
|
||||
getInstruction<TwoRegisterInstruction>(charSequenceIndex).registerA
|
||||
val insertIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.NEW_INSTANCE &&
|
||||
typeReference?.type == textDataClassType
|
||||
}
|
||||
|
||||
val charSequenceIndex = indexOfFirstInstructionOrThrow(insertIndex) {
|
||||
opcode == Opcode.IPUT_OBJECT &&
|
||||
fieldReference?.type == "Ljava/lang/CharSequence;"
|
||||
}
|
||||
val charSequenceRegister =
|
||||
getInstruction<TwoRegisterInstruction>(charSequenceIndex).registerA
|
||||
|
||||
val conversionContext = findFreeRegister(insertIndex, charSequenceRegister)
|
||||
|
||||
addInstructionsAtControlFlowLabel(
|
||||
|
|
@ -194,38 +176,36 @@ val returnYouTubeDislikePatch = bytecodePatch(
|
|||
}
|
||||
|
||||
// Hook new litho text creation code.
|
||||
if (is_20_07_or_greater) {
|
||||
textComponentFeatureFlagMethodMatch.let {
|
||||
it.method.insertLiteralOverride(
|
||||
it[0],
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->useNewLithoTextCreation(Z)Z"
|
||||
textComponentFeatureFlagMethodMatch.let {
|
||||
it.method.insertLiteralOverride(
|
||||
it[0],
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->useNewLithoTextCreation(Z)Z"
|
||||
)
|
||||
}
|
||||
|
||||
lithoSpannableStringCreationMethodMatch.let {
|
||||
val conversionContextField = it.immutableClassDef.type +
|
||||
"->" + textComponentConversionContextField.name +
|
||||
":" + textComponentConversionContextField.type
|
||||
|
||||
it.method.apply {
|
||||
val insertIndex = it[1]
|
||||
val charSequenceRegister =
|
||||
getInstruction<FiveRegisterInstruction>(insertIndex).registerD
|
||||
val conversionContextPathRegister =
|
||||
findFreeRegister(insertIndex, charSequenceRegister)
|
||||
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
move-object/from16 v$conversionContextPathRegister, p0
|
||||
iget-object v$conversionContextPathRegister, v$conversionContextPathRegister, $conversionContextField
|
||||
iget-object v$conversionContextPathRegister, v$conversionContextPathRegister, $conversionContextPathBuilderField
|
||||
invoke-static { v$conversionContextPathRegister, v$charSequenceRegister }, $EXTENSION_CLASS_DESCRIPTOR->onLithoTextLoaded(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
|
||||
move-result-object v$charSequenceRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
lithoSpannableStringCreationMethodMatch.let {
|
||||
val conversionContextField = it.immutableClassDef.type +
|
||||
"->" + textComponentConversionContextField.name +
|
||||
":" + textComponentConversionContextField.type
|
||||
|
||||
it.method.apply {
|
||||
val insertIndex = it[1]
|
||||
val charSequenceRegister =
|
||||
getInstruction<FiveRegisterInstruction>(insertIndex).registerD
|
||||
val conversionContextPathRegister =
|
||||
findFreeRegister(insertIndex, charSequenceRegister)
|
||||
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
move-object/from16 v$conversionContextPathRegister, p0
|
||||
iget-object v$conversionContextPathRegister, v$conversionContextPathRegister, $conversionContextField
|
||||
iget-object v$conversionContextPathRegister, v$conversionContextPathRegister, $conversionContextPathBuilderField
|
||||
invoke-static { v$conversionContextPathRegister, v$charSequenceRegister }, $EXTENSION_CLASS_DESCRIPTOR->onLithoTextLoaded(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
|
||||
move-result-object v$charSequenceRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ import app.revanced.patches.shared.layout.theme.lithoColorHookPatch
|
|||
import app.revanced.patches.shared.layout.theme.lithoColorOverrideHook
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_49_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_21_02_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
|
|
@ -90,20 +88,18 @@ val seekbarColorPatch = bytecodePatch(
|
|||
// If hiding feed seekbar thumbnails, then turn off the cairo gradient
|
||||
// of the watch history menu items as they use the same gradient as the
|
||||
// player and there is no easy way to distinguish which to use a transparent color.
|
||||
if (is_19_34_or_greater) {
|
||||
watchHistoryMenuUseProgressDrawableMethodMatch.let {
|
||||
it.method.apply {
|
||||
val index = it[1]
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
watchHistoryMenuUseProgressDrawableMethodMatch.let {
|
||||
it.method.apply {
|
||||
val index = it[1]
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
addInstructions(
|
||||
index + 1,
|
||||
"""
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->showWatchHistoryProgressDrawable(Z)Z
|
||||
move-result v$register
|
||||
""",
|
||||
)
|
||||
}
|
||||
addInstructions(
|
||||
index + 1,
|
||||
"""
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->showWatchHistoryProgressDrawable(Z)Z
|
||||
move-result v$register
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -115,44 +111,23 @@ val seekbarColorPatch = bytecodePatch(
|
|||
""",
|
||||
)
|
||||
|
||||
val playerMatch: CompositeMatch
|
||||
val checkGradientCoordinates: Boolean
|
||||
if (is_19_49_or_greater) {
|
||||
playerMatch = playerLinearGradientMethodMatch
|
||||
checkGradientCoordinates = true
|
||||
} else {
|
||||
playerMatch = playerLinearGradientLegacyMethodMatch
|
||||
checkGradientCoordinates = false
|
||||
}
|
||||
|
||||
playerMatch.let {
|
||||
playerLinearGradientMethodMatch.let {
|
||||
it.method.apply {
|
||||
val index = it[-1]
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
addInstructions(
|
||||
index + 1,
|
||||
if (checkGradientCoordinates) {
|
||||
"""
|
||||
invoke-static { v$register, p0, p1 }, $EXTENSION_CLASS_DESCRIPTOR->getPlayerLinearGradient([III)[I
|
||||
move-result-object v$register
|
||||
"""
|
||||
} else {
|
||||
"""
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getPlayerLinearGradient([I)[I
|
||||
move-result-object v$register
|
||||
"""
|
||||
},
|
||||
"""
|
||||
invoke-static { v$register, p0, p1 }, $EXTENSION_CLASS_DESCRIPTOR->getPlayerLinearGradient([III)[I
|
||||
move-result-object v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// region apply seekbar custom color to splash screen animation.
|
||||
|
||||
if (!is_19_34_or_greater) {
|
||||
return@apply // 19.25 does not have a cairo launch animation.
|
||||
}
|
||||
|
||||
// Hook the splash animation to set the seekbar color.
|
||||
mainActivityOnCreateMethod.apply {
|
||||
val setAnimationIntMethodName = lottieAnimationViewSetAnimationIntMethod.name
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ import app.revanced.patches.all.misc.resources.addResources
|
|||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_09_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
|
|
@ -35,7 +33,7 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
|||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/ShortsAutoplayPatch;"
|
||||
|
||||
@Suppress("ObjectPropertyName")
|
||||
@Suppress("unused")
|
||||
val shortsAutoplayPatch = bytecodePatch(
|
||||
name = "Shorts autoplay",
|
||||
description = "Adds options to automatically play the next Short.",
|
||||
|
|
@ -65,11 +63,9 @@ val shortsAutoplayPatch = bytecodePatch(
|
|||
SwitchPreference("revanced_shorts_autoplay"),
|
||||
)
|
||||
|
||||
if (is_19_34_or_greater) {
|
||||
PreferenceScreen.SHORTS.addPreferences(
|
||||
SwitchPreference("revanced_shorts_autoplay_background"),
|
||||
)
|
||||
}
|
||||
PreferenceScreen.SHORTS.addPreferences(
|
||||
SwitchPreference("revanced_shorts_autoplay_background"),
|
||||
)
|
||||
|
||||
// Main activity is used to check if app is in pip mode.
|
||||
mainActivityOnCreateMethod.addInstruction(
|
||||
|
|
@ -118,79 +114,78 @@ val shortsAutoplayPatch = bytecodePatch(
|
|||
|
||||
// As of YouTube 20.09, Google has removed the code for 'Autoplay' and 'Pause' from this method.
|
||||
// Manually restore the removed 'Autoplay' code.
|
||||
if (is_20_09_or_greater) {
|
||||
// Variable names are only a rough guess of what these methods do.
|
||||
val userActionMethodReference =
|
||||
reelPlaybackMethodMatch.method.getInstruction(reelPlaybackMethodMatch[1]).methodReference!!
|
||||
val reelSequenceControllerMethodReference =
|
||||
reelPlaybackMethodMatch.method.getInstruction(reelPlaybackMethodMatch[2]).methodReference!!
|
||||
|
||||
reelPlaybackRepeatMethod.apply {
|
||||
// Find the first call modified by extension code above.
|
||||
val extensionReturnResultIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.INVOKE_STATIC &&
|
||||
getReference<MethodReference>()?.definingClass == EXTENSION_CLASS_DESCRIPTOR
|
||||
} + 1
|
||||
val enumRegister =
|
||||
getInstruction<OneRegisterInstruction>(extensionReturnResultIndex).registerA
|
||||
val getReelSequenceControllerIndex = indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<FieldReference>()
|
||||
opcode == Opcode.IGET_OBJECT &&
|
||||
reference?.definingClass == definingClass &&
|
||||
reference.type == reelSequenceControllerMethodReference.definingClass
|
||||
}
|
||||
val getReelSequenceControllerReference =
|
||||
getInstruction<ReferenceInstruction>(getReelSequenceControllerIndex).reference
|
||||
// Variable names are only a rough guess of what these methods do.
|
||||
val userActionMethodReference =
|
||||
reelPlaybackMethodMatch.method.getInstruction(reelPlaybackMethodMatch[1]).methodReference!!
|
||||
val reelSequenceControllerMethodReference =
|
||||
reelPlaybackMethodMatch.method.getInstruction(reelPlaybackMethodMatch[2]).methodReference!!
|
||||
|
||||
// Add a helper method to avoid finding multiple free registers.
|
||||
// If enum is autoplay then method performs autoplay and returns null,
|
||||
// otherwise returns the same enum.
|
||||
val helperClass = definingClass
|
||||
val helperName = "patch_handleAutoPlay"
|
||||
val helperReturnType = "Ljava/lang/Enum;"
|
||||
val helperMethod = ImmutableMethod(
|
||||
helperClass,
|
||||
helperName,
|
||||
listOf(ImmutableMethodParameter("Ljava/lang/Enum;", null, null)),
|
||||
helperReturnType,
|
||||
AccessFlags.PRIVATE.value,
|
||||
null,
|
||||
null,
|
||||
MutableMethodImplementation(7),
|
||||
).toMutable().apply {
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->isAutoPlay(Ljava/lang/Enum;)Z
|
||||
move-result v0
|
||||
if-eqz v0, :ignore
|
||||
new-instance v0, ${userActionMethodReference.definingClass}
|
||||
const/4 v1, 0x3
|
||||
const/4 v2, 0x0
|
||||
invoke-direct { v0, v1, v2, v2 }, $userActionMethodReference
|
||||
iget-object v3, p0, $getReelSequenceControllerReference
|
||||
invoke-virtual { v3, v0 }, $reelSequenceControllerMethodReference
|
||||
const/4 v4, 0x0
|
||||
return-object v4
|
||||
:ignore
|
||||
return-object p1
|
||||
""",
|
||||
)
|
||||
}
|
||||
reelPlaybackRepeatMethod.classDef.methods.add(helperMethod)
|
||||
reelPlaybackRepeatMethod.apply {
|
||||
// Find the first call modified by extension code above.
|
||||
val extensionReturnResultIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.INVOKE_STATIC &&
|
||||
getReference<MethodReference>()?.definingClass == EXTENSION_CLASS_DESCRIPTOR
|
||||
} + 1
|
||||
val enumRegister =
|
||||
getInstruction<OneRegisterInstruction>(extensionReturnResultIndex).registerA
|
||||
val getReelSequenceControllerIndex = indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<FieldReference>()
|
||||
opcode == Opcode.IGET_OBJECT &&
|
||||
reference?.definingClass == definingClass &&
|
||||
reference.type == reelSequenceControllerMethodReference.definingClass
|
||||
}
|
||||
val getReelSequenceControllerReference =
|
||||
getInstruction<ReferenceInstruction>(getReelSequenceControllerIndex).reference
|
||||
|
||||
// Add a helper method to avoid finding multiple free registers.
|
||||
// If enum is autoplay then method performs autoplay and returns null,
|
||||
// otherwise returns the same enum.
|
||||
val helperClass = definingClass
|
||||
val helperName = "patch_handleAutoPlay"
|
||||
val helperReturnType = "Ljava/lang/Enum;"
|
||||
val helperMethod = ImmutableMethod(
|
||||
helperClass,
|
||||
helperName,
|
||||
listOf(ImmutableMethodParameter("Ljava/lang/Enum;", null, null)),
|
||||
helperReturnType,
|
||||
AccessFlags.PRIVATE.value,
|
||||
null,
|
||||
null,
|
||||
MutableMethodImplementation(7),
|
||||
).toMutable().apply {
|
||||
addInstructionsWithLabels(
|
||||
extensionReturnResultIndex + 1,
|
||||
0,
|
||||
"""
|
||||
invoke-direct { p0, v$enumRegister }, $helperClass->$helperName(Ljava/lang/Enum;)$helperReturnType
|
||||
move-result-object v$enumRegister
|
||||
if-nez v$enumRegister, :ignore
|
||||
return-void # Autoplay was performed.
|
||||
invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->isAutoPlay(Ljava/lang/Enum;)Z
|
||||
move-result v0
|
||||
if-eqz v0, :ignore
|
||||
new-instance v0, ${userActionMethodReference.definingClass}
|
||||
const/4 v1, 0x3
|
||||
const/4 v2, 0x0
|
||||
invoke-direct { v0, v1, v2, v2 }, $userActionMethodReference
|
||||
iget-object v3, p0, $getReelSequenceControllerReference
|
||||
invoke-virtual { v3, v0 }, $reelSequenceControllerMethodReference
|
||||
const/4 v4, 0x0
|
||||
return-object v4
|
||||
:ignore
|
||||
nop
|
||||
return-object p1
|
||||
""",
|
||||
)
|
||||
}
|
||||
reelPlaybackRepeatMethod.classDef.methods.add(helperMethod)
|
||||
|
||||
addInstructionsWithLabels(
|
||||
extensionReturnResultIndex + 1,
|
||||
"""
|
||||
invoke-direct { p0, v$enumRegister }, $helperClass->$helperName(Ljava/lang/Enum;)$helperReturnType
|
||||
move-result-object v$enumRegister
|
||||
if-nez v$enumRegister, :ignore
|
||||
return-void # Autoplay was performed.
|
||||
:ignore
|
||||
nop
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,18 +7,11 @@ 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.playservice.is_20_03_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_21_03_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.util.addInstructionsAtControlFlowLabel
|
||||
import app.revanced.util.findFreeRegister
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/DisableResumingStartupShortsPlayerPatch;"
|
||||
|
|
@ -59,40 +52,17 @@ val disableResumingShortsOnStartupPatch = bytecodePatch(
|
|||
SwitchPreference("revanced_disable_resuming_shorts_player"),
|
||||
)
|
||||
|
||||
if (is_20_03_or_greater) {
|
||||
userWasInShortsAlternativeMethodMatch.let {
|
||||
it.method.apply {
|
||||
val insertIndex = it[2] + 1
|
||||
val register = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
userWasInShortsAlternativeMethodMatch.let {
|
||||
it.method.apply {
|
||||
val insertIndex = it[2] + 1
|
||||
val register = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer(Z)Z
|
||||
move-result v$register
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
userWasInShortsLegacyMethod.apply {
|
||||
val listenableInstructionIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.INVOKE_INTERFACE &&
|
||||
getReference<MethodReference>()?.definingClass == "Lcom/google/common/util/concurrent/ListenableFuture;" &&
|
||||
getReference<MethodReference>()?.name == "isDone"
|
||||
}
|
||||
val freeRegister = findFreeRegister(listenableInstructionIndex)
|
||||
|
||||
addInstructionsAtControlFlowLabel(
|
||||
listenableInstructionIndex,
|
||||
"""
|
||||
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z
|
||||
move-result v$freeRegister
|
||||
if-eqz v$freeRegister, :show_startup_shorts_player
|
||||
return-void
|
||||
:show_startup_shorts_player
|
||||
nop
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer(Z)Z
|
||||
move-result v$register
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package app.revanced.patches.youtube.layout.theme
|
||||
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patcher.patch.stringOption
|
||||
|
|
@ -24,8 +24,6 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
|||
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
||||
import app.revanced.patches.youtube.layout.seekbar.seekbarColorPatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_47_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_02_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_21_06_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
|
|
@ -230,24 +228,20 @@ val themePatch = baseThemePatch(
|
|||
),
|
||||
)
|
||||
|
||||
if (is_19_47_or_greater) {
|
||||
PreferenceScreen.GENERAL.addPreferences(
|
||||
ListPreference("revanced_splash_screen_animation_style"),
|
||||
)
|
||||
}
|
||||
PreferenceScreen.GENERAL.addPreferences(
|
||||
ListPreference("revanced_splash_screen_animation_style"),
|
||||
)
|
||||
|
||||
useGradientLoadingScreenMethodMatch.method.insertLiteralOverride(
|
||||
useGradientLoadingScreenMethodMatch[0],
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->gradientLoadingScreenEnabled(Z)Z",
|
||||
)
|
||||
|
||||
if (is_19_47_or_greater) {
|
||||
// Lottie splash screen exists in earlier versions, but it may not be always on.
|
||||
splashScreenStyleMethodMatch.method.insertLiteralOverride(
|
||||
splashScreenStyleMethodMatch[0],
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->getLoadingScreenType(I)I",
|
||||
)
|
||||
}
|
||||
// Lottie splash screen exists in earlier versions, but it may not be always on.
|
||||
splashScreenStyleMethodMatch.method.insertLiteralOverride(
|
||||
splashScreenStyleMethodMatch[0],
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->getLoadingScreenType(I)I",
|
||||
)
|
||||
|
||||
showSplashScreen1MethodMatch.let {
|
||||
it.method.apply {
|
||||
|
|
@ -264,22 +258,20 @@ val themePatch = baseThemePatch(
|
|||
}
|
||||
}
|
||||
|
||||
if (is_20_02_or_greater) {
|
||||
showSplashScreen2MethodMatch.let {
|
||||
val insertIndex = it[1]
|
||||
it.method.apply {
|
||||
val insertInstruction = getInstruction<TwoRegisterInstruction>(insertIndex)
|
||||
val registerA = insertInstruction.registerA
|
||||
val registerB = insertInstruction.registerB
|
||||
showSplashScreen2MethodMatch.let {
|
||||
val insertIndex = it[1]
|
||||
it.method.apply {
|
||||
val insertInstruction = getInstruction<TwoRegisterInstruction>(insertIndex)
|
||||
val registerA = insertInstruction.registerA
|
||||
val registerB = insertInstruction.registerB
|
||||
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static { v$registerA, v$registerB }, ${EXTENSION_CLASS_DESCRIPTOR}->showSplashScreen(II)I
|
||||
move-result v$registerA
|
||||
"""
|
||||
)
|
||||
}
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static { v$registerA, v$registerB }, ${EXTENSION_CLASS_DESCRIPTOR}->showSplashScreen(II)I
|
||||
move-result v$registerA
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
|||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_29_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
|
|
@ -103,13 +102,11 @@ val removeBackgroundPlaybackRestrictionsPatch = bytecodePatch(
|
|||
kidsBackgroundPlaybackPolicyControllerMethod.returnEarly()
|
||||
|
||||
// Fix PiP buttons not working after locking/unlocking device screen.
|
||||
if (is_19_34_or_greater) {
|
||||
pipInputConsumerFeatureFlagMethodMatch.let {
|
||||
it.method.insertLiteralOverride(
|
||||
it[0],
|
||||
false,
|
||||
)
|
||||
}
|
||||
pipInputConsumerFeatureFlagMethodMatch.let {
|
||||
it.method.insertLiteralOverride(
|
||||
it[0],
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
if (is_20_29_or_greater) {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import app.revanced.patcher.extensions.getInstruction
|
|||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.util.findFreeRegister
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
|
|
@ -37,10 +36,6 @@ val fixPlaybackSpeedWhilePlayingPatch = bytecodePatch {
|
|||
)
|
||||
|
||||
apply {
|
||||
if (!is_19_34_or_greater) {
|
||||
return@apply
|
||||
}
|
||||
|
||||
playbackSpeedInFeedsMethod.apply {
|
||||
val playbackSpeedIndex = indexOfGetPlaybackSpeedInstruction(this)
|
||||
val playbackSpeedRegister = getInstruction<TwoRegisterInstruction>(playbackSpeedIndex).registerA
|
||||
|
|
|
|||
|
|
@ -13,17 +13,11 @@ import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
|||
import app.revanced.patches.youtube.misc.playservice.*
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.insertLiteralOverride
|
||||
import app.revanced.util.returnLate
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
val lithoFilterPatch = lithoFilterPatch(
|
||||
componentCreateInsertionIndex = {
|
||||
if (is_19_17_or_greater) {
|
||||
indexOfFirstInstructionOrThrow(Opcode.RETURN_OBJECT)
|
||||
} else {
|
||||
// 19.16 clobbers p2 so must check at start of the method and not at the return index.
|
||||
0
|
||||
}
|
||||
indexOfFirstInstructionOrThrow(Opcode.RETURN_OBJECT)
|
||||
},
|
||||
insertProtobufHook = {
|
||||
if (is_20_22_or_greater) {
|
||||
|
|
@ -49,15 +43,6 @@ val lithoFilterPatch = lithoFilterPatch(
|
|||
executeBlock = {
|
||||
// region A/B test of new Litho native code.
|
||||
|
||||
// Turn off native code that handles litho component names. If this feature is on then nearly
|
||||
// all litho components have a null name and identifier/path filtering is completely broken.
|
||||
//
|
||||
// Flag was removed in 20.05. It appears a new flag might be used instead (45660109L),
|
||||
// but if the flag is forced on then litho filtering still works correctly.
|
||||
if (is_19_25_or_greater && !is_20_05_or_greater) {
|
||||
lithoComponentNameUpbFeatureFlagMethod.returnLate(false)
|
||||
}
|
||||
|
||||
// Turn off a feature flag that enables native code of protobuf parsing (Upb protobuf).
|
||||
lithoConverterBufferUpbFeatureFlagMethodMatch.let {
|
||||
// 20.22 the flag is still enabled in one location, but what it does is not known.
|
||||
|
|
@ -67,6 +52,7 @@ val lithoFilterPatch = lithoFilterPatch(
|
|||
false,
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -27,12 +27,9 @@ import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
|||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction31i
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||
import java.util.logging.Logger
|
||||
|
||||
internal const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/shared/NavigationBar;"
|
||||
|
|
@ -205,25 +202,23 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig
|
|||
}
|
||||
|
||||
// Fix YT bug of notification tab missing the filled icon.
|
||||
if (is_19_35_or_greater) {
|
||||
val cairoNotificationEnumReference =
|
||||
imageEnumConstructorMethodMatch.method.getInstruction(imageEnumConstructorMethodMatch[-1]).reference
|
||||
val cairoNotificationEnumReference =
|
||||
imageEnumConstructorMethodMatch.method.getInstruction(imageEnumConstructorMethodMatch[-1]).reference
|
||||
|
||||
setEnumMapMethodMatch.apply {
|
||||
val setEnumIntegerIndex = setEnumMapMethodMatch[-1]
|
||||
method.apply {
|
||||
val enumMapRegister = getInstruction<FiveRegisterInstruction>(setEnumIntegerIndex).registerC
|
||||
val insertIndex = setEnumIntegerIndex + 1
|
||||
val freeRegister = findFreeRegister(insertIndex, enumMapRegister)
|
||||
setEnumMapMethodMatch.apply {
|
||||
val setEnumIntegerIndex = setEnumMapMethodMatch[-1]
|
||||
method.apply {
|
||||
val enumMapRegister = getInstruction<FiveRegisterInstruction>(setEnumIntegerIndex).registerC
|
||||
val insertIndex = setEnumIntegerIndex + 1
|
||||
val freeRegister = findFreeRegister(insertIndex, enumMapRegister)
|
||||
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
sget-object v$freeRegister, $cairoNotificationEnumReference
|
||||
invoke-static { v$enumMapRegister, v$freeRegister }, $EXTENSION_CLASS_DESCRIPTOR->setCairoNotificationFilledIcon(Ljava/util/EnumMap;Ljava/lang/Enum;)V
|
||||
""",
|
||||
)
|
||||
}
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
sget-object v$freeRegister, $cairoNotificationEnumReference
|
||||
invoke-static { v$enumMapRegister, v$freeRegister }, $EXTENSION_CLASS_DESCRIPTOR->setCairoNotificationFilledIcon(Ljava/util/EnumMap;Ljava/lang/Enum;)V
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -277,16 +277,14 @@ val playerControlsPatch = bytecodePatch(
|
|||
// that uses layout file youtube_video_exploder_controls_bottom_ui_container.xml
|
||||
// The change to support this is simple and only requires adding buttons to both layout files,
|
||||
// but for now force this different layout off since it's still an experimental test.
|
||||
if (is_19_35_or_greater) {
|
||||
playerBottomControlsExploderFeatureFlagMethod.returnLate(false)
|
||||
}
|
||||
playerBottomControlsExploderFeatureFlagMethod.returnLate(false)
|
||||
|
||||
// A/B test of different top overlay controls. Two different layouts can be used:
|
||||
// youtube_cf_navigation_improvement_controls_layout.xml
|
||||
// youtube_cf_minimal_impact_controls_layout.xml
|
||||
//
|
||||
// Flag was removed in 20.19+
|
||||
if (is_19_25_or_greater && !is_20_19_or_greater) {
|
||||
if (!is_20_19_or_greater) {
|
||||
playerTopControlsExperimentalLayoutFeatureFlagMethod.apply {
|
||||
val index = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT_OBJECT)
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
|
|
|||
|
|
@ -8,77 +8,6 @@ import kotlin.properties.Delegates
|
|||
|
||||
// Use notNull delegate so an exception is thrown if these fields are accessed before they are set.
|
||||
|
||||
@Deprecated("20.14.43 is the lowest supported version")
|
||||
var is_19_17_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
|
||||
@Deprecated("20.14.43 is the lowest supported version")
|
||||
var is_19_18_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
|
||||
@Deprecated("20.14.43 is the lowest supported version")
|
||||
var is_19_23_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
|
||||
@Deprecated("20.14.43 is the lowest supported version")
|
||||
var is_19_25_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
|
||||
@Deprecated("20.14.43 is the lowest supported version")
|
||||
var is_19_26_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
|
||||
@Deprecated("20.14.43 is the lowest supported version")
|
||||
var is_19_29_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
|
||||
@Deprecated("20.14.43 is the lowest supported version")
|
||||
var is_19_32_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
|
||||
@Deprecated("20.14.43 is the lowest supported version")
|
||||
var is_19_33_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
|
||||
@Deprecated("20.14.43 is the lowest supported version")
|
||||
var is_19_34_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
|
||||
@Deprecated("20.14.43 is the lowest supported version")
|
||||
var is_19_35_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
|
||||
@Deprecated("20.14.43 is the lowest supported version")
|
||||
var is_19_36_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
|
||||
@Deprecated("20.14.43 is the lowest supported version")
|
||||
var is_19_41_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
|
||||
@Deprecated("20.14.43 is the lowest supported version")
|
||||
var is_19_43_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
var is_19_46_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
var is_19_47_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
var is_19_49_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
var is_20_02_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
var is_20_03_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
var is_20_05_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
var is_20_07_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
var is_20_09_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
var is_20_10_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
var is_20_14_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
var is_20_15_or_greater: Boolean by Delegates.notNull()
|
||||
private set
|
||||
var is_20_19_or_greater: Boolean by Delegates.notNull()
|
||||
|
|
@ -137,29 +66,6 @@ val versionCheckPatch = resourcePatch(
|
|||
val playStoreServicesVersion = findPlayStoreServicesVersion()
|
||||
|
||||
// All bug fix releases always seem to use the same play store version as the minor version.
|
||||
is_19_17_or_greater = 241802000 <= playStoreServicesVersion
|
||||
is_19_18_or_greater = 241902000 <= playStoreServicesVersion
|
||||
is_19_23_or_greater = 242402000 <= playStoreServicesVersion
|
||||
is_19_25_or_greater = 242599000 <= playStoreServicesVersion
|
||||
is_19_26_or_greater = 242705000 <= playStoreServicesVersion
|
||||
is_19_29_or_greater = 243005000 <= playStoreServicesVersion
|
||||
is_19_32_or_greater = 243199000 <= playStoreServicesVersion
|
||||
is_19_33_or_greater = 243405000 <= playStoreServicesVersion
|
||||
is_19_34_or_greater = 243499000 <= playStoreServicesVersion
|
||||
is_19_35_or_greater = 243605000 <= playStoreServicesVersion
|
||||
is_19_36_or_greater = 243705000 <= playStoreServicesVersion
|
||||
is_19_41_or_greater = 244305000 <= playStoreServicesVersion
|
||||
is_19_43_or_greater = 244405000 <= playStoreServicesVersion
|
||||
is_19_46_or_greater = 244705000 <= playStoreServicesVersion
|
||||
is_19_47_or_greater = 244799000 <= playStoreServicesVersion
|
||||
is_19_49_or_greater = 245005000 <= playStoreServicesVersion
|
||||
is_20_02_or_greater = 250299000 <= playStoreServicesVersion
|
||||
is_20_03_or_greater = 250405000 <= playStoreServicesVersion
|
||||
is_20_05_or_greater = 250605000 <= playStoreServicesVersion
|
||||
is_20_07_or_greater = 250805000 <= playStoreServicesVersion
|
||||
is_20_09_or_greater = 251006000 <= playStoreServicesVersion
|
||||
is_20_10_or_greater = 251105000 <= playStoreServicesVersion
|
||||
is_20_14_or_greater = 251505000 <= playStoreServicesVersion
|
||||
is_20_15_or_greater = 251605000 <= playStoreServicesVersion
|
||||
is_20_19_or_greater = 252005000 <= playStoreServicesVersion
|
||||
is_20_20_or_greater = 252105000 <= playStoreServicesVersion
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import app.revanced.patches.youtube.misc.check.checkEnvironmentPatch
|
|||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.fix.contentprovider.fixContentProviderPatch
|
||||
import app.revanced.patches.youtube.misc.fix.playbackspeed.fixPlaybackSpeedWhilePlayingPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_31_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.util.*
|
||||
|
|
@ -187,11 +186,9 @@ val settingsPatch = bytecodePatch(
|
|||
selectable = true,
|
||||
)
|
||||
|
||||
if (is_19_34_or_greater) {
|
||||
PreferenceScreen.GENERAL.addPreferences(
|
||||
SwitchPreference("revanced_restore_old_settings_menus"),
|
||||
)
|
||||
}
|
||||
PreferenceScreen.GENERAL.addPreferences(
|
||||
SwitchPreference("revanced_restore_old_settings_menus"),
|
||||
)
|
||||
|
||||
PreferenceScreen.GENERAL.addPreferences(
|
||||
SwitchPreference("revanced_settings_search_history"),
|
||||
|
|
|
|||
|
|
@ -7,10 +7,6 @@ import app.revanced.patches.shared.misc.settings.preference.NonInteractivePrefer
|
|||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.shared.misc.spoof.spoofVideoStreamsPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_03_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_10_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_14_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
|
|
@ -19,16 +15,9 @@ import app.revanced.patches.youtube.shared.mainActivityOnCreateMethod
|
|||
val spoofVideoStreamsPatch = spoofVideoStreamsPatch(
|
||||
extensionClassDescriptor = "Lapp/revanced/extension/youtube/patches/spoof/SpoofVideoStreamsPatch;",
|
||||
getMainActivityOnCreateMethod = BytecodePatchContext::mainActivityOnCreateMethod::get,
|
||||
fixMediaFetchHotConfig = {
|
||||
is_19_34_or_greater
|
||||
},
|
||||
fixMediaFetchHotConfigAlternative = {
|
||||
// In 20.14 the flag was merged with 20.03 start playback flag.
|
||||
is_20_10_or_greater && !is_20_14_or_greater
|
||||
},
|
||||
fixParsePlaybackResponseFeatureFlag = {
|
||||
is_20_03_or_greater
|
||||
},
|
||||
fixMediaFetchHotConfig = { true },
|
||||
fixMediaFetchHotConfigAlternative = { false },
|
||||
fixParsePlaybackResponseFeatureFlag = { true },
|
||||
|
||||
block = {
|
||||
compatibleWith(
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package app.revanced.patches.youtube.video.audio
|
|||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patches.shared.misc.audio.forceOriginalAudioPatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_07_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
|
|
@ -29,7 +28,7 @@ val forceOriginalAudioPatch = forceOriginalAudioPatch(
|
|||
),
|
||||
)
|
||||
},
|
||||
fixUseLocalizedAudioTrackFlag = { is_20_07_or_greater },
|
||||
fixUseLocalizedAudioTrackFlag = { true },
|
||||
getMainActivityOnCreateMethod = BytecodePatchContext::mainActivityOnCreateMethod::get,
|
||||
subclassExtensionClassDescriptor = "Lapp/revanced/extension/youtube/patches/ForceOriginalAudioPatch;",
|
||||
preferenceScreen = PreferenceScreen.VIDEO,
|
||||
|
|
|
|||
|
|
@ -5,9 +5,6 @@ import app.revanced.patcher.extensions.addInstruction
|
|||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_23_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_02_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_10_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_15_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_26_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_46_or_greater
|
||||
|
|
@ -50,18 +47,9 @@ val playerResponseMethodHookPatch = bytecodePatch {
|
|||
} else if (is_20_15_or_greater) {
|
||||
parameterIsShortAndOpeningOrPlaying = 13
|
||||
method = playerParameterBuilder2015Method
|
||||
} else if (is_20_10_or_greater) {
|
||||
} else {
|
||||
parameterIsShortAndOpeningOrPlaying = 13
|
||||
method = playerParameterBuilder2010Method
|
||||
} else if (is_20_02_or_greater) {
|
||||
parameterIsShortAndOpeningOrPlaying = 12
|
||||
method = playerParameterBuilder2002Method
|
||||
} else if (is_19_23_or_greater) {
|
||||
parameterIsShortAndOpeningOrPlaying = 12
|
||||
method = playerParameterBuilder1925Method
|
||||
} else {
|
||||
parameterIsShortAndOpeningOrPlaying = 11
|
||||
method = playerParameterBuilderLegacyMethod
|
||||
}
|
||||
playerResponseMethod = method
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
|||
import app.revanced.patches.shared.misc.litho.filter.addLithoFilter
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.litho.filter.lithoFilterPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_47_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.recyclerviewtree.hook.addRecyclerViewTreeHook
|
||||
|
|
@ -65,11 +64,9 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
|
|||
),
|
||||
)
|
||||
|
||||
if (is_19_47_or_greater) {
|
||||
settingsMenuVideoSpeedGroup.add(
|
||||
TextPreference("revanced_speed_tap_and_hold", inputType = InputType.NUMBER_DECIMAL),
|
||||
)
|
||||
}
|
||||
settingsMenuVideoSpeedGroup.add(
|
||||
TextPreference("revanced_speed_tap_and_hold", inputType = InputType.NUMBER_DECIMAL),
|
||||
)
|
||||
|
||||
// Override the min/max speeds that can be used.
|
||||
(if (is_20_34_or_greater) speedLimiterMethod else speedLimiterLegacyMethod).apply {
|
||||
|
|
@ -171,22 +168,20 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
|
|||
|
||||
// region Custom tap and hold 2x speed.
|
||||
|
||||
if (is_19_47_or_greater) {
|
||||
// Function, because it can be the same method as getTapAndHoldHapticsMethodMatch.
|
||||
getTapAndHoldSpeedMethodMatch().let {
|
||||
it.method.apply {
|
||||
val speedIndex = it[-1]
|
||||
val speedRegister =
|
||||
getInstruction<OneRegisterInstruction>(speedIndex).registerA
|
||||
// Function, because it can be the same method as getTapAndHoldHapticsMethodMatch.
|
||||
getTapAndHoldSpeedMethodMatch().let {
|
||||
it.method.apply {
|
||||
val speedIndex = it[-1]
|
||||
val speedRegister =
|
||||
getInstruction<OneRegisterInstruction>(speedIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
speedIndex + 1,
|
||||
"""
|
||||
invoke-static { }, ${EXTENSION_CLASS_DESCRIPTOR}->getTapAndHoldSpeed()F
|
||||
move-result v$speedRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
addInstructions(
|
||||
speedIndex + 1,
|
||||
"""
|
||||
invoke-static { }, ${EXTENSION_CLASS_DESCRIPTOR}->getTapAndHoldSpeed()F
|
||||
move-result v$speedRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue