mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-04-29 22:24:27 +02:00
feat(YouTube - Remember video quality): Add separate Shorts default quality settings (#4543)
This commit is contained in:
parent
74ec83f964
commit
88142ab464
@ -158,16 +158,16 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
/**
|
||||
* Syncs all UI Preferences to any {@link Setting} they represent.
|
||||
*/
|
||||
private void updatePreferenceScreen(@NonNull PreferenceScreen screen,
|
||||
private void updatePreferenceScreen(@NonNull PreferenceGroup group,
|
||||
boolean syncSettingValue,
|
||||
boolean applySettingToPreference) {
|
||||
// Alternatively this could iterate thru all Settings and check for any matching Preferences,
|
||||
// but there are many more Settings than UI preferences so it's more efficient to only check
|
||||
// the Preferences.
|
||||
for (int i = 0, prefCount = screen.getPreferenceCount(); i < prefCount; i++) {
|
||||
Preference pref = screen.getPreference(i);
|
||||
if (pref instanceof PreferenceScreen) {
|
||||
updatePreferenceScreen((PreferenceScreen) pref, syncSettingValue, applySettingToPreference);
|
||||
for (int i = 0, prefCount = group.getPreferenceCount(); i < prefCount; i++) {
|
||||
Preference pref = group.getPreference(i);
|
||||
if (pref instanceof PreferenceGroup subGroup) {
|
||||
updatePreferenceScreen(subGroup, syncSettingValue, applySettingToPreference);
|
||||
} else if (pref.hasKey()) {
|
||||
String key = pref.getKey();
|
||||
Setting<?> setting = Setting.getSettingFromPath(key);
|
||||
|
@ -0,0 +1,34 @@
|
||||
package app.revanced.extension.shared.settings.preference;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
/**
|
||||
* Empty preference category with no title, used to organize and group related preferences together.
|
||||
*/
|
||||
@SuppressWarnings({"unused", "deprecation"})
|
||||
public class NoTitlePreferenceCategory extends PreferenceCategory {
|
||||
public NoTitlePreferenceCategory(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public NoTitlePreferenceCategory(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public NoTitlePreferenceCategory(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressLint("MissingSuperCall")
|
||||
protected View onCreateView(ViewGroup parent) {
|
||||
// Return an empty, zero-height view to eliminate spacing
|
||||
return new View(getContext());
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
import app.revanced.extension.youtube.shared.ShortsPlayerState;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class BackgroundPlaybackPatch {
|
||||
@ -23,16 +23,7 @@ public class BackgroundPlaybackPatch {
|
||||
// 7. Close the Short
|
||||
// 8. Resume playing the regular video
|
||||
// 9. Minimize the app (PIP should appear)
|
||||
if (!VideoInformation.lastVideoIdIsShort()) {
|
||||
return true; // Definitely is not a Short.
|
||||
}
|
||||
|
||||
// TODO: Add better hook.
|
||||
// Might be a Shorts, or might be a prior regular video on screen again after a Shorts was closed.
|
||||
// This incorrectly prevents PIP if player is in WATCH_WHILE_MINIMIZED after closing a Shorts,
|
||||
// But there's no way around this unless an additional hook is added to definitively detect
|
||||
// the Shorts player is on screen. This use case is unusual anyways so it's not a huge concern.
|
||||
return !PlayerType.getCurrent().isNoneHiddenOrMinimized();
|
||||
return !ShortsPlayerState.isOpen();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,7 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
import app.revanced.extension.youtube.shared.ShortsPlayerState;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class DisableAutoCaptionsPatch {
|
||||
@ -14,7 +14,7 @@ public class DisableAutoCaptionsPatch {
|
||||
public static boolean autoCaptionsEnabled() {
|
||||
return Settings.AUTO_CAPTIONS.get()
|
||||
// Do not use auto captions for Shorts.
|
||||
&& !PlayerType.getCurrent().isNoneHiddenOrSlidingMinimized();
|
||||
&& ShortsPlayerState.isOpen();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,8 +1,11 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
import app.revanced.extension.youtube.shared.ShortsPlayerState;
|
||||
import app.revanced.extension.youtube.shared.VideoState;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ -24,4 +27,26 @@ public class PlayerTypeHookPatch {
|
||||
|
||||
VideoState.setFromString(youTubeVideoState.name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*
|
||||
* Add a listener to the shorts player overlay View.
|
||||
* Triggered when a shorts player is attached or detached to Windows.
|
||||
*
|
||||
* @param view shorts player overlay (R.id.reel_watch_player).
|
||||
*/
|
||||
public static void onShortsCreate(View view) {
|
||||
view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
|
||||
@Override
|
||||
public void onViewAttachedToWindow(@Nullable View v) {
|
||||
ShortsPlayerState.setOpen(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(@Nullable View v) {
|
||||
ShortsPlayerState.setOpen(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -12,15 +12,19 @@ import java.util.List;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BooleanSetting;
|
||||
import app.revanced.extension.shared.settings.IntegerSetting;
|
||||
import app.revanced.extension.youtube.patches.VideoInformation;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.ShortsPlayerState;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class RememberVideoQualityPatch {
|
||||
private static final int AUTOMATIC_VIDEO_QUALITY_VALUE = -2;
|
||||
private static final IntegerSetting wifiQualitySetting = Settings.VIDEO_QUALITY_DEFAULT_WIFI;
|
||||
private static final IntegerSetting mobileQualitySetting = Settings.VIDEO_QUALITY_DEFAULT_MOBILE;
|
||||
private static final IntegerSetting videoQualityWifi = Settings.VIDEO_QUALITY_DEFAULT_WIFI;
|
||||
private static final IntegerSetting videoQualityMobile = Settings.VIDEO_QUALITY_DEFAULT_MOBILE;
|
||||
private static final IntegerSetting shortsQualityWifi = Settings.SHORTS_QUALITY_DEFAULT_WIFI;
|
||||
private static final IntegerSetting shortsQualityMobile = Settings.SHORTS_QUALITY_DEFAULT_MOBILE;
|
||||
|
||||
private static boolean qualityNeedsUpdating;
|
||||
|
||||
@ -41,17 +45,29 @@ public class RememberVideoQualityPatch {
|
||||
@Nullable
|
||||
private static List<Integer> videoQualities;
|
||||
|
||||
private static boolean shouldRememberVideoQuality() {
|
||||
BooleanSetting preference = ShortsPlayerState.isOpen() ?
|
||||
Settings.REMEMBER_SHORTS_QUALITY_LAST_SELECTED
|
||||
: Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED;
|
||||
return preference.get();
|
||||
}
|
||||
|
||||
private static void changeDefaultQuality(int defaultQuality) {
|
||||
String networkTypeMessage;
|
||||
boolean useShortsPreference = ShortsPlayerState.isOpen();
|
||||
if (Utils.getNetworkType() == NetworkType.MOBILE) {
|
||||
mobileQualitySetting.save(defaultQuality);
|
||||
if (useShortsPreference) shortsQualityMobile.save(defaultQuality);
|
||||
else videoQualityMobile.save(defaultQuality);
|
||||
networkTypeMessage = str("revanced_remember_video_quality_mobile");
|
||||
} else {
|
||||
wifiQualitySetting.save(defaultQuality);
|
||||
if (useShortsPreference) shortsQualityWifi.save(defaultQuality);
|
||||
else videoQualityWifi.save(defaultQuality);
|
||||
networkTypeMessage = str("revanced_remember_video_quality_wifi");
|
||||
}
|
||||
Utils.showToastShort(
|
||||
str("revanced_remember_video_quality_toast", networkTypeMessage, (defaultQuality + "p")));
|
||||
Utils.showToastShort(str(
|
||||
useShortsPreference ? "revanced_remember_video_quality_toast_shorts" : "revanced_remember_video_quality_toast",
|
||||
networkTypeMessage, (defaultQuality + "p")
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -62,9 +78,10 @@ public class RememberVideoQualityPatch {
|
||||
*/
|
||||
public static int setVideoQuality(Object[] qualities, final int originalQualityIndex, Object qInterface, String qIndexMethod) {
|
||||
try {
|
||||
boolean useShortsPreference = ShortsPlayerState.isOpen();
|
||||
final int preferredQuality = Utils.getNetworkType() == NetworkType.MOBILE
|
||||
? mobileQualitySetting.get()
|
||||
: wifiQualitySetting.get();
|
||||
? (useShortsPreference ? shortsQualityMobile : videoQualityMobile).get()
|
||||
: (useShortsPreference ? shortsQualityWifi : videoQualityWifi).get();
|
||||
|
||||
if (!userChangedDefaultQuality && preferredQuality == AUTOMATIC_VIDEO_QUALITY_VALUE) {
|
||||
return originalQualityIndex; // Nothing to do.
|
||||
@ -141,17 +158,17 @@ public class RememberVideoQualityPatch {
|
||||
* Injection point. Old quality menu.
|
||||
*/
|
||||
public static void userChangedQuality(int selectedQualityIndex) {
|
||||
if (!Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED.get()) return;
|
||||
|
||||
userSelectedQualityIndex = selectedQualityIndex;
|
||||
userChangedDefaultQuality = true;
|
||||
if (shouldRememberVideoQuality()) {
|
||||
userSelectedQualityIndex = selectedQualityIndex;
|
||||
userChangedDefaultQuality = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point. New quality menu.
|
||||
*/
|
||||
public static void userChangedQualityInNewFlyout(int selectedQuality) {
|
||||
if (!Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED.get()) return;
|
||||
if (!shouldRememberVideoQuality()) return;
|
||||
|
||||
changeDefaultQuality(selectedQuality); // Quality is human readable resolution (ie: 1080).
|
||||
}
|
||||
|
@ -48,10 +48,13 @@ import app.revanced.extension.youtube.sponsorblock.SponsorBlockSettings;
|
||||
public class Settings extends BaseSettings {
|
||||
// Video
|
||||
public static final BooleanSetting DISABLE_HDR_VIDEO = new BooleanSetting("revanced_disable_hdr_video", FALSE);
|
||||
public static final BooleanSetting RESTORE_OLD_VIDEO_QUALITY_MENU = new BooleanSetting("revanced_restore_old_video_quality_menu", TRUE);
|
||||
public static final BooleanSetting REMEMBER_VIDEO_QUALITY_LAST_SELECTED = new BooleanSetting("revanced_remember_video_quality_last_selected", FALSE);
|
||||
public static final IntegerSetting VIDEO_QUALITY_DEFAULT_WIFI = new IntegerSetting("revanced_video_quality_default_wifi", -2);
|
||||
public static final IntegerSetting VIDEO_QUALITY_DEFAULT_MOBILE = new IntegerSetting("revanced_video_quality_default_mobile", -2);
|
||||
public static final BooleanSetting REMEMBER_VIDEO_QUALITY_LAST_SELECTED = new BooleanSetting("revanced_remember_video_quality_last_selected", FALSE);
|
||||
public static final IntegerSetting SHORTS_QUALITY_DEFAULT_WIFI = new IntegerSetting("revanced_shorts_quality_default_wifi", -2, true);
|
||||
public static final IntegerSetting SHORTS_QUALITY_DEFAULT_MOBILE = new IntegerSetting("revanced_shorts_quality_default_mobile", -2, true);
|
||||
public static final BooleanSetting REMEMBER_SHORTS_QUALITY_LAST_SELECTED = new BooleanSetting("revanced_remember_shorts_quality_last_selected", FALSE);
|
||||
public static final BooleanSetting RESTORE_OLD_VIDEO_QUALITY_MENU = new BooleanSetting("revanced_restore_old_video_quality_menu", TRUE);
|
||||
// Speed
|
||||
public static final FloatSetting SPEED_TAP_AND_HOLD = new FloatSetting("revanced_speed_tap_and_hold", 2.0f, true);
|
||||
public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED = new BooleanSetting("revanced_remember_playback_speed_last_selected", FALSE);
|
||||
|
@ -5,7 +5,7 @@ import app.revanced.extension.youtube.Event
|
||||
import app.revanced.extension.youtube.patches.VideoInformation
|
||||
|
||||
/**
|
||||
* Main player type.
|
||||
* Regular player type.
|
||||
*/
|
||||
enum class PlayerType {
|
||||
/**
|
||||
@ -90,8 +90,6 @@ enum class PlayerType {
|
||||
* Does not include the first moment after a short is opened when a regular video is minimized on screen,
|
||||
* or while watching a short with a regular video present on a spoofed 16.x version of YouTube.
|
||||
* To include those situations instead use [isNoneHiddenOrMinimized].
|
||||
*
|
||||
* @see VideoInformation
|
||||
*/
|
||||
fun isNoneOrHidden(): Boolean {
|
||||
return this == NONE || this == HIDDEN
|
||||
@ -107,8 +105,11 @@ enum class PlayerType {
|
||||
* when spoofing to an old version this will return false even
|
||||
* though a Short is being opened or is on screen (see [isNoneHiddenOrMinimized]).
|
||||
*
|
||||
* Instead of this method, consider using {@link ShortsPlayerState}
|
||||
* which may work better for some situations.
|
||||
*
|
||||
* @return If nothing, a Short, or a regular video is sliding off screen to a dismissed or hidden state.
|
||||
* @see VideoInformation
|
||||
* @see ShortsPlayerState
|
||||
*/
|
||||
fun isNoneHiddenOrSlidingMinimized(): Boolean {
|
||||
return isNoneOrHidden() || this == WATCH_WHILE_SLIDING_MINIMIZED_DISMISSED
|
||||
@ -125,9 +126,12 @@ enum class PlayerType {
|
||||
* Typically used to detect if a Short is playing when the player cannot be in a minimized state,
|
||||
* such as the user interacting with a button or element of the player.
|
||||
*
|
||||
* Instead of this method, consider using {@link ShortsPlayerState}
|
||||
* which may work better for some situations.
|
||||
*
|
||||
* @return If nothing, a Short, a regular video is sliding off screen to a dismissed or hidden state,
|
||||
* a regular video is minimized (and a new video is not being opened).
|
||||
* @see VideoInformation
|
||||
* @see ShortsPlayerState
|
||||
*/
|
||||
fun isNoneHiddenOrMinimized(): Boolean {
|
||||
return isNoneHiddenOrSlidingMinimized() || this == WATCH_WHILE_MINIMIZED
|
||||
|
@ -0,0 +1,38 @@
|
||||
package app.revanced.extension.youtube.shared
|
||||
|
||||
import app.revanced.extension.shared.Logger
|
||||
import app.revanced.extension.youtube.Event
|
||||
|
||||
/**
|
||||
* Shorts player state.
|
||||
*/
|
||||
class ShortsPlayerState {
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun setOpen(open: Boolean) {
|
||||
if (isOpen != open) {
|
||||
Logger.printDebug { "ShortsPlayerState open changed to: $isOpen" }
|
||||
isOpen = open
|
||||
onChange(open)
|
||||
}
|
||||
}
|
||||
|
||||
@Volatile
|
||||
private var isOpen = false
|
||||
|
||||
/**
|
||||
* Shorts player state change listener.
|
||||
*/
|
||||
@JvmStatic
|
||||
val onChange = Event<Boolean>()
|
||||
|
||||
/**
|
||||
* If the Shorts player is currently open.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isOpen(): Boolean {
|
||||
return isOpen
|
||||
}
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ import org.w3c.dom.Element
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
abstract class BasePreference(
|
||||
val key: String? = null,
|
||||
val titleKey: String = "${key}_title",
|
||||
val titleKey: String? = "${key}_title",
|
||||
val summaryKey: String? = "${key}_summary",
|
||||
val icon: String? = null,
|
||||
val layout: String? = null,
|
||||
@ -35,7 +35,7 @@ abstract class BasePreference(
|
||||
open fun serialize(ownerDocument: Document, resourceCallback: (BaseResource) -> Unit): Element =
|
||||
ownerDocument.createElement(tag).apply {
|
||||
key?.let { setAttribute("android:key", it) }
|
||||
setAttribute("android:title", "@string/${titleKey}")
|
||||
titleKey?.let { setAttribute("android:title", "@string/${titleKey}") }
|
||||
summaryKey?.let { addSummary(it) }
|
||||
icon?.let {
|
||||
setAttribute("android:icon", it)
|
||||
|
@ -17,7 +17,7 @@ import org.w3c.dom.Document
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
open class PreferenceCategory(
|
||||
key: String? = null,
|
||||
titleKey: String = "${key}_title",
|
||||
titleKey: String? = "${key}_title",
|
||||
icon: String? = null,
|
||||
layout: String? = null,
|
||||
sorting: Sorting = Sorting.BY_TITLE,
|
||||
|
@ -12,6 +12,8 @@ import app.revanced.patches.shared.misc.mapping.get
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||
import app.revanced.patches.shared.misc.settings.preference.ListPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceCategory
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
|
||||
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
|
||||
@ -71,20 +73,31 @@ val spoofAppVersionPatch = bytecodePatch(
|
||||
addResources("youtube", "layout.spoofappversion.spoofAppVersionPatch")
|
||||
|
||||
PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||
SwitchPreference("revanced_spoof_app_version"),
|
||||
if (is_19_17_or_greater) {
|
||||
ListPreference(
|
||||
key = "revanced_spoof_app_version_target",
|
||||
summaryKey = null,
|
||||
// Group the switch and list preference together, since General menu is sorted by name
|
||||
// and the preferences can be scattered apart with non English langauges.
|
||||
PreferenceCategory(
|
||||
key = null,
|
||||
// The title does not show, but is used for sorting the group.
|
||||
titleKey = "revanced_spoof_app_version_title",
|
||||
sorting = Sorting.UNSORTED,
|
||||
tag = "app.revanced.extension.shared.settings.preference.NoTitlePreferenceCategory",
|
||||
preferences = setOf(
|
||||
SwitchPreference("revanced_spoof_app_version"),
|
||||
if (is_19_17_or_greater) {
|
||||
ListPreference(
|
||||
key = "revanced_spoof_app_version_target",
|
||||
summaryKey = null,
|
||||
)
|
||||
} else {
|
||||
ListPreference(
|
||||
key = "revanced_spoof_app_version_target",
|
||||
summaryKey = null,
|
||||
entriesKey = "revanced_spoof_app_version_target_legacy_entries",
|
||||
entryValuesKey = "revanced_spoof_app_version_target_legacy_entry_values"
|
||||
)
|
||||
}
|
||||
)
|
||||
} else {
|
||||
ListPreference(
|
||||
key = "revanced_spoof_app_version_target",
|
||||
summaryKey = null,
|
||||
entriesKey = "revanced_spoof_app_version_target_legacy_entries",
|
||||
entryValuesKey = "revanced_spoof_app_version_target_legacy_entry_values"
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,7 @@
|
||||
package app.revanced.patches.youtube.misc.playertype
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
@ -15,6 +16,12 @@ internal val playerTypeFingerprint = fingerprint {
|
||||
custom { _, classDef -> classDef.endsWith("/YouTubePlayerOverlaysLayout;") }
|
||||
}
|
||||
|
||||
internal val reelWatchPagerFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("Landroid/view/View;")
|
||||
literal { reelWatchPlayerId }
|
||||
}
|
||||
|
||||
internal val videoStateFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
|
@ -4,15 +4,34 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patches.shared.misc.mapping.get
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
|
||||
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/PlayerTypeHookPatch;"
|
||||
|
||||
internal var reelWatchPlayerId = -1L
|
||||
private set
|
||||
|
||||
private val playerTypeHookResourcePatch = resourcePatch {
|
||||
dependsOn(resourceMappingPatch)
|
||||
|
||||
execute {
|
||||
reelWatchPlayerId = resourceMappings["id", "reel_watch_player"]
|
||||
}
|
||||
}
|
||||
|
||||
val playerTypeHookPatch = bytecodePatch(
|
||||
description = "Hook to get the current player type and video playback state.",
|
||||
) {
|
||||
dependsOn(sharedExtensionPatch)
|
||||
dependsOn(sharedExtensionPatch, playerTypeHookResourcePatch)
|
||||
|
||||
execute {
|
||||
playerTypeFingerprint.method.addInstruction(
|
||||
@ -20,6 +39,17 @@ val playerTypeHookPatch = bytecodePatch(
|
||||
"invoke-static {p1}, $EXTENSION_CLASS_DESCRIPTOR->setPlayerType(Ljava/lang/Enum;)V",
|
||||
)
|
||||
|
||||
reelWatchPagerFingerprint.method.apply {
|
||||
val literalIndex = indexOfFirstLiteralInstructionOrThrow(reelWatchPlayerId)
|
||||
val registerIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT_OBJECT)
|
||||
val viewRegister = getInstruction<OneRegisterInstruction>(registerIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
registerIndex + 1,
|
||||
"invoke-static { v$viewRegister }, $EXTENSION_CLASS_DESCRIPTOR->onShortsCreate(Landroid/view/View;)V"
|
||||
)
|
||||
}
|
||||
|
||||
videoStateFingerprint.method.apply {
|
||||
val endIndex = videoStateFingerprint.patternMatch!!.endIndex
|
||||
val videoStateFieldName = getInstruction<ReferenceInstruction>(endIndex).reference
|
||||
@ -27,9 +57,9 @@ val playerTypeHookPatch = bytecodePatch(
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
iget-object v0, p1, $videoStateFieldName # copy VideoState parameter field
|
||||
invoke-static {v0}, $EXTENSION_CLASS_DESCRIPTOR->setVideoState(Ljava/lang/Enum;)V
|
||||
""",
|
||||
iget-object v0, p1, $videoStateFieldName # copy VideoState parameter field
|
||||
invoke-static {v0}, $EXTENSION_CLASS_DESCRIPTOR->setVideoState(Ljava/lang/Enum;)V
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -323,6 +323,7 @@ object PreferenceScreen : BasePreferenceScreen() {
|
||||
val VIDEO = Screen(
|
||||
key = "revanced_settings_screen_12_video",
|
||||
summaryKey = null,
|
||||
sorting = Sorting.BY_KEY,
|
||||
)
|
||||
|
||||
override fun commit(screen: PreferenceScreenPreference) {
|
||||
|
@ -8,8 +8,11 @@ import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.ListPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceCategory
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
|
||||
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.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.shared.newVideoQualityChangedFingerprint
|
||||
@ -29,6 +32,7 @@ val rememberVideoQualityPatch = bytecodePatch(
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
videoInformationPatch,
|
||||
playerTypeHookPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
)
|
||||
@ -49,19 +53,42 @@ val rememberVideoQualityPatch = bytecodePatch(
|
||||
addResources("youtube", "video.quality.rememberVideoQualityPatch")
|
||||
|
||||
PreferenceScreen.VIDEO.addPreferences(
|
||||
SwitchPreference("revanced_remember_video_quality_last_selected"),
|
||||
ListPreference(
|
||||
key = "revanced_video_quality_default_wifi",
|
||||
summaryKey = null,
|
||||
entriesKey = "revanced_video_quality_default_entries",
|
||||
entryValuesKey = "revanced_video_quality_default_entry_values",
|
||||
),
|
||||
ListPreference(
|
||||
key = "revanced_video_quality_default_mobile",
|
||||
summaryKey = null,
|
||||
entriesKey = "revanced_video_quality_default_entries",
|
||||
entryValuesKey = "revanced_video_quality_default_entry_values",
|
||||
),
|
||||
// Keep the preferences organized together.
|
||||
PreferenceCategory(
|
||||
key = "revanced_01_video_key", // Dummy key to force the quality preferences first.
|
||||
titleKey = null,
|
||||
sorting = Sorting.UNSORTED,
|
||||
tag = "app.revanced.extension.shared.settings.preference.NoTitlePreferenceCategory",
|
||||
preferences = setOf(
|
||||
ListPreference(
|
||||
key = "revanced_video_quality_default_mobile",
|
||||
summaryKey = null,
|
||||
entriesKey = "revanced_video_quality_default_entries",
|
||||
entryValuesKey = "revanced_video_quality_default_entry_values",
|
||||
),
|
||||
ListPreference(
|
||||
key = "revanced_video_quality_default_wifi",
|
||||
summaryKey = null,
|
||||
entriesKey = "revanced_video_quality_default_entries",
|
||||
entryValuesKey = "revanced_video_quality_default_entry_values",
|
||||
),
|
||||
SwitchPreference("revanced_remember_video_quality_last_selected"),
|
||||
|
||||
ListPreference(
|
||||
key = "revanced_shorts_quality_default_mobile",
|
||||
summaryKey = null,
|
||||
entriesKey = "revanced_video_quality_default_entries",
|
||||
entryValuesKey = "revanced_video_quality_default_entry_values",
|
||||
),
|
||||
ListPreference(
|
||||
key = "revanced_shorts_quality_default_wifi",
|
||||
summaryKey = null,
|
||||
entriesKey = "revanced_video_quality_default_entries",
|
||||
entryValuesKey = "revanced_video_quality_default_entry_values",
|
||||
),
|
||||
SwitchPreference("revanced_remember_shorts_quality_last_selected")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -1,10 +1,19 @@
|
||||
package app.revanced.patches.youtube.video.speed
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.BasePreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceCategory
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.video.speed.button.playbackSpeedButtonPatch
|
||||
import app.revanced.patches.youtube.video.speed.custom.customPlaybackSpeedPatch
|
||||
import app.revanced.patches.youtube.video.speed.remember.rememberPlaybackSpeedPatch
|
||||
|
||||
/**
|
||||
* Speed menu settings. Used to organize all speed related settings together.
|
||||
*/
|
||||
internal val settingsMenuVideoSpeedGroup = mutableSetOf<BasePreference>()
|
||||
|
||||
@Suppress("unused")
|
||||
val playbackSpeedPatch = bytecodePatch(
|
||||
name = "Playback speed",
|
||||
@ -26,6 +35,18 @@ val playbackSpeedPatch = bytecodePatch(
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
finalize {
|
||||
PreferenceScreen.VIDEO.addPreferences(
|
||||
PreferenceCategory(
|
||||
key = "revanced_zz_key", // Dummy key to force the speed settings last.
|
||||
titleKey = null,
|
||||
sorting = Sorting.UNSORTED,
|
||||
tag = "app.revanced.extension.shared.settings.preference.NoTitlePreferenceCategory",
|
||||
preferences = settingsMenuVideoSpeedGroup
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,8 @@ import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.recyclerviewtree.hook.addRecyclerViewTreeHook
|
||||
import app.revanced.patches.youtube.misc.recyclerviewtree.hook.recyclerViewTreeHookPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.video.speed.settingsMenuVideoSpeedGroup
|
||||
import app.revanced.util.*
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||
@ -71,13 +71,18 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
|
||||
execute {
|
||||
addResources("youtube", "video.speed.custom.customPlaybackSpeedPatch")
|
||||
|
||||
PreferenceScreen.VIDEO.addPreferences(
|
||||
SwitchPreference("revanced_custom_speed_menu"),
|
||||
TextPreference("revanced_custom_playback_speeds", inputType = InputType.TEXT_MULTI_LINE),
|
||||
settingsMenuVideoSpeedGroup.addAll(
|
||||
listOf(
|
||||
SwitchPreference("revanced_custom_speed_menu"),
|
||||
TextPreference(
|
||||
"revanced_custom_playback_speeds",
|
||||
inputType = InputType.TEXT_MULTI_LINE
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
if (is_19_25_or_greater) {
|
||||
PreferenceScreen.VIDEO.addPreferences(
|
||||
settingsMenuVideoSpeedGroup.add(
|
||||
TextPreference("revanced_speed_tap_and_hold", inputType = InputType.NUMBER_DECIMAL),
|
||||
)
|
||||
}
|
||||
|
@ -9,10 +9,10 @@ import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.ListPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.video.information.*
|
||||
import app.revanced.patches.youtube.video.speed.custom.customPlaybackSpeedPatch
|
||||
import app.revanced.patches.youtube.video.speed.settingsMenuVideoSpeedGroup
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
@ -30,15 +30,17 @@ internal val rememberPlaybackSpeedPatch = bytecodePatch {
|
||||
execute {
|
||||
addResources("youtube", "video.speed.remember.rememberPlaybackSpeedPatch")
|
||||
|
||||
PreferenceScreen.VIDEO.addPreferences(
|
||||
SwitchPreference("revanced_remember_playback_speed_last_selected"),
|
||||
ListPreference(
|
||||
key = "revanced_playback_speed_default",
|
||||
summaryKey = null,
|
||||
// Entries and values are set by the extension code based on the actual speeds available.
|
||||
entriesKey = null,
|
||||
entryValuesKey = null,
|
||||
),
|
||||
settingsMenuVideoSpeedGroup.addAll(
|
||||
listOf(
|
||||
ListPreference(
|
||||
key = "revanced_playback_speed_default",
|
||||
summaryKey = null,
|
||||
// Entries and values are set by the extension code based on the actual speeds available.
|
||||
entriesKey = null,
|
||||
entryValuesKey = null,
|
||||
),
|
||||
SwitchPreference("revanced_remember_playback_speed_last_selected")
|
||||
)
|
||||
)
|
||||
|
||||
onCreateHook(EXTENSION_CLASS_DESCRIPTOR, "newVideoStarted")
|
||||
|
@ -1373,15 +1373,22 @@ Enabling this can unlock higher video qualities"</string>
|
||||
</patch>
|
||||
<patch id="video.quality.rememberVideoQualityPatch">
|
||||
<!-- Translations should use the same text as revanced_custom_playback_speeds_auto -->
|
||||
<string name="revanced_video_quality_screen_title">Video quality</string>
|
||||
<string name="revanced_video_quality_default_entry_1">Auto</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_title">Remember video quality changes</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_summary_on">Quality changes apply to all videos</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_summary_off">Quality changes only apply to the current video</string>
|
||||
<string name="revanced_video_quality_default_wifi_title">Default video quality on Wi-Fi network</string>
|
||||
<string name="revanced_video_quality_default_mobile_title">Default video quality on mobile network</string>
|
||||
<string name="revanced_remember_shorts_quality_last_selected_title">Remember Shorts quality changes</string>
|
||||
<string name="revanced_remember_shorts_quality_last_selected_summary_on">Quality changes apply to all Shorts videos</string>
|
||||
<string name="revanced_remember_shorts_quality_last_selected_summary_off">Quality changes only apply to the current Shorts video</string>
|
||||
<string name="revanced_shorts_quality_default_wifi_title">Default Shorts quality on Wi-Fi network</string>
|
||||
<string name="revanced_shorts_quality_default_mobile_title">Default Shorts quality on mobile network</string>
|
||||
<string name="revanced_remember_video_quality_mobile">mobile</string>
|
||||
<string name="revanced_remember_video_quality_wifi">wifi</string>
|
||||
<string name="revanced_remember_video_quality_toast">Changed default %1$s quality to: %2$s</string>
|
||||
<string name="revanced_remember_video_quality_toast_shorts">Changed Shorts %1$s quality to: %2$s</string>
|
||||
</patch>
|
||||
<patch id="video.speed.button.playbackSpeedButtonPatch">
|
||||
<string name="revanced_playback_speed_dialog_button_title">Show speed dialog button</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user