mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-04-30 06:34:28 +02:00
fix(YouTube - Spoof app version): Remove broken spoof targets that YouTube no longer supports (#4610)
This commit is contained in:
parent
2090f7ec8f
commit
883fbe7123
@ -21,7 +21,6 @@ import java.util.Objects;
|
|||||||
import app.revanced.extension.shared.Logger;
|
import app.revanced.extension.shared.Logger;
|
||||||
import app.revanced.extension.shared.Utils;
|
import app.revanced.extension.shared.Utils;
|
||||||
import app.revanced.extension.youtube.patches.components.ReturnYouTubeDislikeFilterPatch;
|
import app.revanced.extension.youtube.patches.components.ReturnYouTubeDislikeFilterPatch;
|
||||||
import app.revanced.extension.youtube.patches.spoof.SpoofAppVersionPatch;
|
|
||||||
import app.revanced.extension.youtube.returnyoutubedislike.ReturnYouTubeDislike;
|
import app.revanced.extension.youtube.returnyoutubedislike.ReturnYouTubeDislike;
|
||||||
import app.revanced.extension.youtube.returnyoutubedislike.requests.ReturnYouTubeDislikeApi;
|
import app.revanced.extension.youtube.returnyoutubedislike.requests.ReturnYouTubeDislikeApi;
|
||||||
import app.revanced.extension.youtube.settings.Settings;
|
import app.revanced.extension.youtube.settings.Settings;
|
||||||
@ -47,9 +46,6 @@ import app.revanced.extension.youtube.shared.PlayerType;
|
|||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class ReturnYouTubeDislikePatch {
|
public class ReturnYouTubeDislikePatch {
|
||||||
|
|
||||||
public static final boolean IS_SPOOFING_TO_NON_LITHO_SHORTS_PLAYER =
|
|
||||||
SpoofAppVersionPatch.isSpoofingToLessThan("18.34.00");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RYD data for the current video on screen.
|
* RYD data for the current video on screen.
|
||||||
*/
|
*/
|
||||||
@ -347,137 +343,6 @@ public class ReturnYouTubeDislikePatch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Non litho Shorts player.
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replacement text to use for "Dislikes" while RYD is fetching.
|
|
||||||
*/
|
|
||||||
private static final Spannable SHORTS_LOADING_SPAN = new SpannableString("-");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dislikes TextViews used by Shorts.
|
|
||||||
*
|
|
||||||
* Multiple TextViews are loaded at once (for the prior and next videos to swipe to).
|
|
||||||
* Keep track of all of them, and later pick out the correct one based on their on screen position.
|
|
||||||
*/
|
|
||||||
private static final List<WeakReference<TextView>> shortsTextViewRefs = new ArrayList<>();
|
|
||||||
|
|
||||||
private static void clearRemovedShortsTextViews() {
|
|
||||||
shortsTextViewRefs.removeIf(ref -> ref.get() == null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Injection point. Called when a Shorts dislike is updated. Always on main thread.
|
|
||||||
* Handles update asynchronously, otherwise Shorts video will be frozen while the UI thread is blocked.
|
|
||||||
*
|
|
||||||
* @return if RYD is enabled and the TextView was updated.
|
|
||||||
*/
|
|
||||||
public static boolean setShortsDislikes(@NonNull View likeDislikeView) {
|
|
||||||
try {
|
|
||||||
if (!Settings.RYD_ENABLED.get()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!Settings.RYD_SHORTS.get() || Settings.HIDE_SHORTS_DISLIKE_BUTTON.get()) {
|
|
||||||
// Must clear the data here, in case a new video was loaded while PlayerType
|
|
||||||
// suggested the video was not a short (can happen when spoofing to an old app version).
|
|
||||||
clearData();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Logger.printDebug(() -> "setShortsDislikes");
|
|
||||||
|
|
||||||
TextView textView = (TextView) likeDislikeView;
|
|
||||||
textView.setText(SHORTS_LOADING_SPAN); // Change 'Dislike' text to the loading text.
|
|
||||||
shortsTextViewRefs.add(new WeakReference<>(textView));
|
|
||||||
|
|
||||||
if (likeDislikeView.isSelected() && isShortTextViewOnScreen(textView)) {
|
|
||||||
Logger.printDebug(() -> "Shorts dislike is already selected");
|
|
||||||
ReturnYouTubeDislike videoData = currentVideoData;
|
|
||||||
if (videoData != null) videoData.setUserVote(Vote.DISLIKE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// For the first short played, the Shorts dislike hook is called after the video id hook.
|
|
||||||
// But for most other times this hook is called before the video id (which is not ideal).
|
|
||||||
// Must update the TextViews here, and also after the videoId changes.
|
|
||||||
updateOnScreenShortsTextViews(false);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (Exception ex) {
|
|
||||||
Logger.printException(() -> "setShortsDislikes failure", ex);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param forceUpdate if false, then only update the 'loading text views.
|
|
||||||
* If true, update all on screen text views.
|
|
||||||
*/
|
|
||||||
private static void updateOnScreenShortsTextViews(boolean forceUpdate) {
|
|
||||||
try {
|
|
||||||
clearRemovedShortsTextViews();
|
|
||||||
if (shortsTextViewRefs.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ReturnYouTubeDislike videoData = currentVideoData;
|
|
||||||
if (videoData == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.printDebug(() -> "updateShortsTextViews");
|
|
||||||
|
|
||||||
Runnable update = () -> {
|
|
||||||
Spanned shortsDislikesSpan = videoData.getDislikeSpanForShort(SHORTS_LOADING_SPAN);
|
|
||||||
Utils.runOnMainThreadNowOrLater(() -> {
|
|
||||||
String videoId = videoData.getVideoId();
|
|
||||||
if (!videoId.equals(VideoInformation.getVideoId())) {
|
|
||||||
// User swiped to new video before fetch completed
|
|
||||||
Logger.printDebug(() -> "Ignoring stale dislikes data for short: " + videoId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update text views that appear to be visible on screen.
|
|
||||||
// Only 1 will be the actual textview for the current Short,
|
|
||||||
// but discarded and not yet garbage collected views can remain.
|
|
||||||
// So must set the dislike span on all views that match.
|
|
||||||
for (WeakReference<TextView> textViewRef : shortsTextViewRefs) {
|
|
||||||
TextView textView = textViewRef.get();
|
|
||||||
if (textView == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (isShortTextViewOnScreen(textView)
|
|
||||||
&& (forceUpdate || textView.getText().toString().equals(SHORTS_LOADING_SPAN.toString()))) {
|
|
||||||
Logger.printDebug(() -> "Setting Shorts TextView to: " + shortsDislikesSpan);
|
|
||||||
textView.setText(shortsDislikesSpan);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
if (videoData.fetchCompleted()) {
|
|
||||||
update.run(); // Network call is completed, no need to wait on background thread.
|
|
||||||
} else {
|
|
||||||
Utils.runOnBackgroundThread(update);
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
Logger.printException(() -> "updateOnScreenShortsTextViews failure", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a view is within the screen bounds.
|
|
||||||
*/
|
|
||||||
private static boolean isShortTextViewOnScreen(@NonNull View view) {
|
|
||||||
final int[] location = new int[2];
|
|
||||||
view.getLocationInWindow(location);
|
|
||||||
if (location[0] <= 0 && location[1] <= 0) { // Lower bound
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Rect windowRect = new Rect();
|
|
||||||
view.getWindowVisibleDisplayFrame(windowRect); // Upper bound
|
|
||||||
return location[0] < windowRect.width() && location[1] < windowRect.height();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Video Id and voting hooks (all players).
|
// Video Id and voting hooks (all players).
|
||||||
//
|
//
|
||||||
@ -503,8 +368,7 @@ public class ReturnYouTubeDislikePatch {
|
|||||||
if (videoIdIsShort && (!isShortAndOpeningOrPlaying || !Settings.RYD_SHORTS.get())) {
|
if (videoIdIsShort && (!isShortAndOpeningOrPlaying || !Settings.RYD_SHORTS.get())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final boolean waitForFetchToComplete = !IS_SPOOFING_TO_NON_LITHO_SHORTS_PLAYER
|
final boolean waitForFetchToComplete = videoIdIsShort && !lastPlayerResponseWasShort;
|
||||||
&& videoIdIsShort && !lastPlayerResponseWasShort;
|
|
||||||
|
|
||||||
Logger.printDebug(() -> "Prefetching RYD for video: " + videoId);
|
Logger.printDebug(() -> "Prefetching RYD for video: " + videoId);
|
||||||
ReturnYouTubeDislike fetch = ReturnYouTubeDislike.getFetchForVideoId(videoId);
|
ReturnYouTubeDislike fetch = ReturnYouTubeDislike.getFetchForVideoId(videoId);
|
||||||
@ -557,12 +421,6 @@ public class ReturnYouTubeDislikePatch {
|
|||||||
data.setVideoIdIsShort(true);
|
data.setVideoIdIsShort(true);
|
||||||
}
|
}
|
||||||
currentVideoData = data;
|
currentVideoData = data;
|
||||||
|
|
||||||
// Current video id hook can be called out of order with the non litho Shorts text view hook.
|
|
||||||
// Must manually update again here.
|
|
||||||
if (isNoneHiddenOrSlidingMinimized) {
|
|
||||||
updateOnScreenShortsTextViews(true);
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.printException(() -> "newVideoLoaded failure", ex);
|
Logger.printException(() -> "newVideoLoaded failure", ex);
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,6 @@ import java.util.concurrent.*;
|
|||||||
import app.revanced.extension.shared.Logger;
|
import app.revanced.extension.shared.Logger;
|
||||||
import app.revanced.extension.shared.Utils;
|
import app.revanced.extension.shared.Utils;
|
||||||
import app.revanced.extension.youtube.ThemeHelper;
|
import app.revanced.extension.youtube.ThemeHelper;
|
||||||
import app.revanced.extension.youtube.patches.spoof.SpoofAppVersionPatch;
|
|
||||||
import app.revanced.extension.youtube.returnyoutubedislike.requests.RYDVoteData;
|
import app.revanced.extension.youtube.returnyoutubedislike.requests.RYDVoteData;
|
||||||
import app.revanced.extension.youtube.returnyoutubedislike.requests.ReturnYouTubeDislikeApi;
|
import app.revanced.extension.youtube.returnyoutubedislike.requests.ReturnYouTubeDislikeApi;
|
||||||
import app.revanced.extension.youtube.settings.Settings;
|
import app.revanced.extension.youtube.settings.Settings;
|
||||||
@ -87,9 +86,6 @@ public class ReturnYouTubeDislike {
|
|||||||
*/
|
*/
|
||||||
private static final char MIDDLE_SEPARATOR_CHARACTER = '◎'; // 'bullseye'
|
private static final char MIDDLE_SEPARATOR_CHARACTER = '◎'; // 'bullseye'
|
||||||
|
|
||||||
private static final boolean IS_SPOOFING_TO_OLD_SEPARATOR_COLOR
|
|
||||||
= SpoofAppVersionPatch.isSpoofingToLessThan("18.10.00");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cached lookup of all video ids.
|
* Cached lookup of all video ids.
|
||||||
*/
|
*/
|
||||||
@ -184,17 +180,8 @@ public class ReturnYouTubeDislike {
|
|||||||
* Color of the left and middle separator, based on the color of the right separator.
|
* Color of the left and middle separator, based on the color of the right separator.
|
||||||
* It's unknown where YT gets the color from, and the values here are approximated by hand.
|
* It's unknown where YT gets the color from, and the values here are approximated by hand.
|
||||||
* Ideally, this would be the actual color YT uses at runtime.
|
* Ideally, this would be the actual color YT uses at runtime.
|
||||||
*
|
|
||||||
* Older versions before the 'Me' library tab use a slightly different color.
|
|
||||||
* If spoofing was previously used and is now turned off,
|
|
||||||
* or an old version was recently upgraded then the old colors are sometimes still used.
|
|
||||||
*/
|
*/
|
||||||
private static int getSeparatorColor() {
|
private static int getSeparatorColor() {
|
||||||
if (IS_SPOOFING_TO_OLD_SEPARATOR_COLOR) {
|
|
||||||
return ThemeHelper.isDarkTheme()
|
|
||||||
? 0x29AAAAAA // transparent dark gray
|
|
||||||
: 0xFFD9D9D9; // light gray
|
|
||||||
}
|
|
||||||
return ThemeHelper.isDarkTheme()
|
return ThemeHelper.isDarkTheme()
|
||||||
? 0x33FFFFFF
|
? 0x33FFFFFF
|
||||||
: 0xFFD9D9D9;
|
: 0xFFD9D9D9;
|
||||||
|
@ -3,7 +3,6 @@ package app.revanced.extension.youtube.settings;
|
|||||||
import static java.lang.Boolean.FALSE;
|
import static java.lang.Boolean.FALSE;
|
||||||
import static java.lang.Boolean.TRUE;
|
import static java.lang.Boolean.TRUE;
|
||||||
import static app.revanced.extension.shared.settings.Setting.Availability;
|
import static app.revanced.extension.shared.settings.Setting.Availability;
|
||||||
import static app.revanced.extension.shared.settings.Setting.migrateFromOldPreferences;
|
|
||||||
import static app.revanced.extension.shared.settings.Setting.migrateOldSettingToNew;
|
import static app.revanced.extension.shared.settings.Setting.migrateOldSettingToNew;
|
||||||
import static app.revanced.extension.shared.settings.Setting.parent;
|
import static app.revanced.extension.shared.settings.Setting.parent;
|
||||||
import static app.revanced.extension.shared.settings.Setting.parentsAny;
|
import static app.revanced.extension.shared.settings.Setting.parentsAny;
|
||||||
@ -21,7 +20,6 @@ import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerT
|
|||||||
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MODERN_4;
|
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MODERN_4;
|
||||||
import static app.revanced.extension.youtube.patches.OpenShortsInRegularPlayerPatch.ShortsPlayerType;
|
import static app.revanced.extension.youtube.patches.OpenShortsInRegularPlayerPatch.ShortsPlayerType;
|
||||||
import static app.revanced.extension.youtube.patches.SeekbarThumbnailsPatch.SeekbarThumbnailsHighQualityAvailability;
|
import static app.revanced.extension.youtube.patches.SeekbarThumbnailsPatch.SeekbarThumbnailsHighQualityAvailability;
|
||||||
import static app.revanced.extension.youtube.patches.VersionCheckPatch.IS_19_17_OR_GREATER;
|
|
||||||
import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.IGNORE;
|
import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.IGNORE;
|
||||||
import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.MANUAL_SKIP;
|
import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.MANUAL_SKIP;
|
||||||
import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.SKIP_AUTOMATICALLY;
|
import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.SKIP_AUTOMATICALLY;
|
||||||
@ -38,7 +36,6 @@ import app.revanced.extension.shared.settings.IntegerSetting;
|
|||||||
import app.revanced.extension.shared.settings.LongSetting;
|
import app.revanced.extension.shared.settings.LongSetting;
|
||||||
import app.revanced.extension.shared.settings.Setting;
|
import app.revanced.extension.shared.settings.Setting;
|
||||||
import app.revanced.extension.shared.settings.StringSetting;
|
import app.revanced.extension.shared.settings.StringSetting;
|
||||||
import app.revanced.extension.shared.settings.preference.SharedPrefCategory;
|
|
||||||
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.DeArrowAvailability;
|
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.DeArrowAvailability;
|
||||||
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.StillImagesAvailability;
|
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.StillImagesAvailability;
|
||||||
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.ThumbnailOption;
|
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.ThumbnailOption;
|
||||||
@ -221,7 +218,7 @@ public class Settings extends BaseSettings {
|
|||||||
public static final BooleanSetting SPOOF_APP_VERSION = new BooleanSetting("revanced_spoof_app_version", FALSE, true, "revanced_spoof_app_version_user_dialog_message");
|
public static final BooleanSetting SPOOF_APP_VERSION = new BooleanSetting("revanced_spoof_app_version", FALSE, true, "revanced_spoof_app_version_user_dialog_message");
|
||||||
public static final BooleanSetting WIDE_SEARCHBAR = new BooleanSetting("revanced_wide_searchbar", FALSE, true);
|
public static final BooleanSetting WIDE_SEARCHBAR = new BooleanSetting("revanced_wide_searchbar", FALSE, true);
|
||||||
public static final EnumSetting<StartPage> CHANGE_START_PAGE = new EnumSetting<>("revanced_change_start_page", StartPage.DEFAULT, true);
|
public static final EnumSetting<StartPage> CHANGE_START_PAGE = new EnumSetting<>("revanced_change_start_page", StartPage.DEFAULT, true);
|
||||||
public static final StringSetting SPOOF_APP_VERSION_TARGET = new StringSetting("revanced_spoof_app_version_target", IS_19_17_OR_GREATER ? "19.26.42" : "17.33.42", true, parent(SPOOF_APP_VERSION));
|
public static final StringSetting SPOOF_APP_VERSION_TARGET = new StringSetting("revanced_spoof_app_version_target", "19.26.42", true, parent(SPOOF_APP_VERSION));
|
||||||
// Custom filter
|
// Custom filter
|
||||||
public static final BooleanSetting CUSTOM_FILTER = new BooleanSetting("revanced_custom_filter", FALSE);
|
public static final BooleanSetting CUSTOM_FILTER = new BooleanSetting("revanced_custom_filter", FALSE);
|
||||||
public static final StringSetting CUSTOM_FILTER_STRINGS = new StringSetting("revanced_custom_filter_strings", "", true, parent(CUSTOM_FILTER));
|
public static final StringSetting CUSTOM_FILTER_STRINGS = new StringSetting("revanced_custom_filter_strings", "", true, parent(CUSTOM_FILTER));
|
||||||
@ -395,7 +392,6 @@ public class Settings extends BaseSettings {
|
|||||||
public static final FloatSetting SB_CATEGORY_UNSUBMITTED_OPACITY = new FloatSetting("sb_unsubmitted_opacity", 1.0f);
|
public static final FloatSetting SB_CATEGORY_UNSUBMITTED_OPACITY = new FloatSetting("sb_unsubmitted_opacity", 1.0f);
|
||||||
|
|
||||||
// Deprecated migrations
|
// Deprecated migrations
|
||||||
private static final StringSetting DEPRECATED_SB_UUID_OLD_MIGRATION_SETTING = new StringSetting("uuid", ""); // Delete sometime in 2024
|
|
||||||
private static final BooleanSetting DEPRECATED_HIDE_PLAYER_BUTTONS = new BooleanSetting("revanced_hide_player_buttons", FALSE, true);
|
private static final BooleanSetting DEPRECATED_HIDE_PLAYER_BUTTONS = new BooleanSetting("revanced_hide_player_buttons", FALSE, true);
|
||||||
private static final BooleanSetting DEPRECATED_HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER = new BooleanSetting("revanced_hide_video_quality_menu_footer", FALSE);
|
private static final BooleanSetting DEPRECATED_HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER = new BooleanSetting("revanced_hide_video_quality_menu_footer", FALSE);
|
||||||
private static final IntegerSetting DEPRECATED_SWIPE_OVERLAY_BACKGROUND_ALPHA = new IntegerSetting("revanced_swipe_overlay_background_alpha", 127);
|
private static final IntegerSetting DEPRECATED_SWIPE_OVERLAY_BACKGROUND_ALPHA = new IntegerSetting("revanced_swipe_overlay_background_alpha", 127);
|
||||||
@ -406,16 +402,6 @@ public class Settings extends BaseSettings {
|
|||||||
static {
|
static {
|
||||||
// region Migration
|
// region Migration
|
||||||
|
|
||||||
// Do _not_ delete this SB private user id migration property until sometime in early 2025.
|
|
||||||
// This is the only setting that cannot be reconfigured if lost,
|
|
||||||
// and more time should be given for users who rarely upgrade.
|
|
||||||
SharedPrefCategory sbPrefs = new SharedPrefCategory("sponsor-block");
|
|
||||||
// Remove the "sb_" prefix, as old settings are saved without it.
|
|
||||||
String key = DEPRECATED_SB_UUID_OLD_MIGRATION_SETTING.key.substring(3);
|
|
||||||
migrateFromOldPreferences(sbPrefs, DEPRECATED_SB_UUID_OLD_MIGRATION_SETTING, key);
|
|
||||||
|
|
||||||
migrateOldSettingToNew(DEPRECATED_SB_UUID_OLD_MIGRATION_SETTING, SB_PRIVATE_USER_ID);
|
|
||||||
|
|
||||||
migrateOldSettingToNew(DEPRECATED_HIDE_PLAYER_BUTTONS, HIDE_PLAYER_PREVIOUS_NEXT_BUTTONS);
|
migrateOldSettingToNew(DEPRECATED_HIDE_PLAYER_BUTTONS, HIDE_PLAYER_PREVIOUS_NEXT_BUTTONS);
|
||||||
|
|
||||||
migrateOldSettingToNew(DEPRECATED_HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER, HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER);
|
migrateOldSettingToNew(DEPRECATED_HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER, HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER);
|
||||||
@ -459,6 +445,12 @@ public class Settings extends BaseSettings {
|
|||||||
DEPRECATED_SWIPE_OVERLAY_BACKGROUND_ALPHA.resetToDefault();
|
DEPRECATED_SWIPE_OVERLAY_BACKGROUND_ALPHA.resetToDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Old spoof versions that no longer work.
|
||||||
|
if (SPOOF_APP_VERSION_TARGET.get().compareTo(SPOOF_APP_VERSION_TARGET.defaultValue) < 0) {
|
||||||
|
Logger.printInfo(() -> "Resetting spoof app version target");
|
||||||
|
SPOOF_APP_VERSION_TARGET.resetToDefault();
|
||||||
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region SB import/export callbacks
|
// region SB import/export callbacks
|
||||||
|
@ -86,9 +86,7 @@ public class ReturnYouTubeDislikePreferenceFragment extends PreferenceFragment {
|
|||||||
shortsPreference = new SwitchPreference(context);
|
shortsPreference = new SwitchPreference(context);
|
||||||
shortsPreference.setChecked(Settings.RYD_SHORTS.get());
|
shortsPreference.setChecked(Settings.RYD_SHORTS.get());
|
||||||
shortsPreference.setTitle(str("revanced_ryd_shorts_title"));
|
shortsPreference.setTitle(str("revanced_ryd_shorts_title"));
|
||||||
String shortsSummary = ReturnYouTubeDislikePatch.IS_SPOOFING_TO_NON_LITHO_SHORTS_PLAYER
|
String shortsSummary = str("revanced_ryd_shorts_summary_on_disclaimer");
|
||||||
? str("revanced_ryd_shorts_summary_on")
|
|
||||||
: str("revanced_ryd_shorts_summary_on_disclaimer");
|
|
||||||
shortsPreference.setSummaryOn(shortsSummary);
|
shortsPreference.setSummaryOn(shortsSummary);
|
||||||
shortsPreference.setSummaryOff(str("revanced_ryd_shorts_summary_off"));
|
shortsPreference.setSummaryOff(str("revanced_ryd_shorts_summary_off"));
|
||||||
shortsPreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
shortsPreference.setOnPreferenceChangeListener((pref, newValue) -> {
|
||||||
|
@ -98,20 +98,6 @@ internal val rollingNumberTextViewFingerprint = fingerprint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val shortsTextViewFingerprint = fingerprint {
|
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
|
||||||
returns("V")
|
|
||||||
parameters("L", "L")
|
|
||||||
opcodes(
|
|
||||||
Opcode.INVOKE_SUPER, // first instruction of method
|
|
||||||
Opcode.IF_NEZ,
|
|
||||||
null,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.CHECK_CAST,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal val textComponentConstructorFingerprint = fingerprint {
|
internal val textComponentConstructorFingerprint = fingerprint {
|
||||||
accessFlags(AccessFlags.CONSTRUCTOR, AccessFlags.PRIVATE)
|
accessFlags(AccessFlags.CONSTRUCTOR, AccessFlags.PRIVATE)
|
||||||
strings("TextComponent")
|
strings("TextComponent")
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package app.revanced.patches.youtube.layout.returnyoutubedislike
|
package app.revanced.patches.youtube.layout.returnyoutubedislike
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
|
||||||
import app.revanced.patcher.patch.PatchException
|
import app.revanced.patcher.patch.PatchException
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import app.revanced.patches.all.misc.resources.addResources
|
import app.revanced.patches.all.misc.resources.addResources
|
||||||
@ -169,51 +167,7 @@ val returnYouTubeDislikePatch = bytecodePatch(
|
|||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Hook for non-litho Short videos.
|
// region Hook Shorts
|
||||||
shortsTextViewFingerprint.method.apply {
|
|
||||||
val insertIndex = shortsTextViewFingerprint.patternMatch!!.endIndex + 1
|
|
||||||
|
|
||||||
// If the field is true, the TextView is for a dislike button.
|
|
||||||
val isDisLikesBooleanInstruction = instructions.first { instruction ->
|
|
||||||
instruction.opcode == Opcode.IGET_BOOLEAN
|
|
||||||
} as ReferenceInstruction
|
|
||||||
|
|
||||||
val isDisLikesBooleanReference = isDisLikesBooleanInstruction.reference
|
|
||||||
|
|
||||||
// Like/Dislike button TextView field.
|
|
||||||
val textViewFieldInstruction = instructions.first { instruction ->
|
|
||||||
instruction.opcode == Opcode.IGET_OBJECT
|
|
||||||
} as ReferenceInstruction
|
|
||||||
|
|
||||||
val textViewFieldReference = textViewFieldInstruction.reference
|
|
||||||
|
|
||||||
// Check if the hooked TextView object is that of the dislike button.
|
|
||||||
// If RYD is disabled, or the TextView object is not that of the dislike button, the execution flow is not interrupted.
|
|
||||||
// Otherwise, the TextView object is modified, and the execution flow is interrupted to prevent it from being changed afterward.
|
|
||||||
addInstructionsWithLabels(
|
|
||||||
insertIndex,
|
|
||||||
"""
|
|
||||||
# Check, if the TextView is for a dislike button
|
|
||||||
iget-boolean v0, p0, $isDisLikesBooleanReference
|
|
||||||
if-eqz v0, :is_like
|
|
||||||
|
|
||||||
# Hook the TextView, if it is for the dislike button
|
|
||||||
iget-object v0, p0, $textViewFieldReference
|
|
||||||
invoke-static {v0}, $EXTENSION_CLASS_DESCRIPTOR->setShortsDislikes(Landroid/view/View;)Z
|
|
||||||
move-result v0
|
|
||||||
if-eqz v0, :ryd_disabled
|
|
||||||
return-void
|
|
||||||
|
|
||||||
:is_like
|
|
||||||
:ryd_disabled
|
|
||||||
nop
|
|
||||||
""",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Hook for litho Shorts
|
|
||||||
|
|
||||||
// Filter that parses the video id from the UI
|
// Filter that parses the video id from the UI
|
||||||
addLithoFilter(FILTER_CLASS_DESCRIPTOR)
|
addLithoFilter(FILTER_CLASS_DESCRIPTOR)
|
||||||
@ -255,22 +209,25 @@ val returnYouTubeDislikePatch = bytecodePatch(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rolling Number text views use the measured width of the raw string for layout.
|
rollingNumberMeasureAnimatedTextFingerprint.let {
|
||||||
// Modify the measure text calculation to include the left drawable separator if needed.
|
// Rolling Number text views use the measured width of the raw string for layout.
|
||||||
val patternMatch = rollingNumberMeasureAnimatedTextFingerprint.patternMatch!!
|
// Modify the measure text calculation to include the left drawable separator if needed.
|
||||||
// Additional check to verify the opcodes are at the start of the method
|
val patternMatch = it.patternMatch!!
|
||||||
if (patternMatch.startIndex != 0) throw PatchException("Unexpected opcode location")
|
// Verify the opcodes are at the start of the method.
|
||||||
val endIndex = patternMatch.endIndex
|
if (patternMatch.startIndex != 0) throw PatchException("Unexpected opcode location")
|
||||||
rollingNumberMeasureAnimatedTextFingerprint.method.apply {
|
val endIndex = patternMatch.endIndex
|
||||||
val measuredTextWidthRegister = getInstruction<OneRegisterInstruction>(endIndex).registerA
|
|
||||||
|
|
||||||
addInstructions(
|
it.method.apply {
|
||||||
endIndex + 1,
|
val measuredTextWidthRegister = getInstruction<OneRegisterInstruction>(endIndex).registerA
|
||||||
"""
|
|
||||||
invoke-static {p1, v$measuredTextWidthRegister}, $EXTENSION_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F
|
addInstructions(
|
||||||
move-result v$measuredTextWidthRegister
|
endIndex + 1,
|
||||||
""",
|
"""
|
||||||
)
|
invoke-static {p1, v$measuredTextWidthRegister}, $EXTENSION_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F
|
||||||
|
move-result v$measuredTextWidthRegister
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Additional text measurement method. Used if YouTube decides not to animate the likes count
|
// Additional text measurement method. Used if YouTube decides not to animate the likes count
|
||||||
@ -291,15 +248,14 @@ val returnYouTubeDislikePatch = bytecodePatch(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// The rolling number Span is missing styling since it's initially set as a String.
|
|
||||||
// Modify the UI text view and use the styled like/dislike Span.
|
|
||||||
// Initial TextView is set in this method.
|
|
||||||
val initiallyCreatedTextViewMethod = rollingNumberTextViewFingerprint.method
|
|
||||||
|
|
||||||
// Videos less than 24 hours after uploaded, like counts will be updated in real time.
|
|
||||||
// Whenever like counts are updated, TextView is set in this method.
|
|
||||||
arrayOf(
|
arrayOf(
|
||||||
initiallyCreatedTextViewMethod,
|
// The rolling number Span is missing styling since it's initially set as a String.
|
||||||
|
// Modify the UI text view and use the styled like/dislike Span.
|
||||||
|
// Initial TextView is set in this method.
|
||||||
|
rollingNumberTextViewFingerprint.method,
|
||||||
|
// Videos less than 24 hours after uploaded, like counts will be updated in real time.
|
||||||
|
// Whenever like counts are updated, TextView is set in this method.
|
||||||
rollingNumberTextViewAnimationUpdateFingerprint.method,
|
rollingNumberTextViewAnimationUpdateFingerprint.method,
|
||||||
).forEach { insertMethod ->
|
).forEach { insertMethod ->
|
||||||
insertMethod.apply {
|
insertMethod.apply {
|
||||||
@ -315,9 +271,9 @@ val returnYouTubeDislikePatch = bytecodePatch(
|
|||||||
addInstructions(
|
addInstructions(
|
||||||
setTextIndex,
|
setTextIndex,
|
||||||
"""
|
"""
|
||||||
invoke-static {v$textViewRegister, v$textSpanRegister}, $EXTENSION_CLASS_DESCRIPTOR->updateRollingNumber(Landroid/widget/TextView;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
|
invoke-static {v$textViewRegister, v$textSpanRegister}, $EXTENSION_CLASS_DESCRIPTOR->updateRollingNumber(Landroid/widget/TextView;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
|
||||||
move-result-object v$textSpanRegister
|
move-result-object v$textSpanRegister
|
||||||
""",
|
"""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@ 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.PreferenceScreenPreference.Sorting
|
||||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
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.playservice.versionCheckPatch
|
||||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||||
@ -46,8 +45,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR =
|
|||||||
val spoofAppVersionPatch = bytecodePatch(
|
val spoofAppVersionPatch = bytecodePatch(
|
||||||
name = "Spoof app version",
|
name = "Spoof app version",
|
||||||
description = "Adds an option to trick YouTube into thinking you are running an older version of the app. " +
|
description = "Adds an option to trick YouTube into thinking you are running an older version of the app. " +
|
||||||
"This can be used to restore old UI elements and features. " +
|
"This can be used to restore old UI elements and features."
|
||||||
"Patching 19.16.39 includes additional older spoofing targets.",
|
|
||||||
) {
|
) {
|
||||||
dependsOn(
|
dependsOn(
|
||||||
spoofAppVersionResourcePatch,
|
spoofAppVersionResourcePatch,
|
||||||
@ -59,7 +57,7 @@ val spoofAppVersionPatch = bytecodePatch(
|
|||||||
|
|
||||||
compatibleWith(
|
compatibleWith(
|
||||||
"com.google.android.youtube"(
|
"com.google.android.youtube"(
|
||||||
"19.16.39",
|
// "19.16.39", // Cannot be supported because the lowest spoof target is higher.
|
||||||
// "19.25.37", // Cannot be supported because the lowest spoof target is higher.
|
// "19.25.37", // Cannot be supported because the lowest spoof target is higher.
|
||||||
// "19.34.42", // Cannot be supported because the lowest spoof target is higher.
|
// "19.34.42", // Cannot be supported because the lowest spoof target is higher.
|
||||||
"19.43.41",
|
"19.43.41",
|
||||||
@ -81,19 +79,10 @@ val spoofAppVersionPatch = bytecodePatch(
|
|||||||
tag = "app.revanced.extension.shared.settings.preference.NoTitlePreferenceCategory",
|
tag = "app.revanced.extension.shared.settings.preference.NoTitlePreferenceCategory",
|
||||||
preferences = setOf(
|
preferences = setOf(
|
||||||
SwitchPreference("revanced_spoof_app_version"),
|
SwitchPreference("revanced_spoof_app_version"),
|
||||||
if (is_19_17_or_greater) {
|
ListPreference(
|
||||||
ListPreference(
|
key = "revanced_spoof_app_version_target",
|
||||||
key = "revanced_spoof_app_version_target",
|
summaryKey = null,
|
||||||
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"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -143,24 +143,9 @@
|
|||||||
<item>@string/revanced_spoof_app_version_target_entry_2</item>
|
<item>@string/revanced_spoof_app_version_target_entry_2</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="revanced_spoof_app_version_target_entry_values">
|
<string-array name="revanced_spoof_app_version_target_entry_values">
|
||||||
<!-- Patching 19.23+ or later cannot spoof to 19.20 or lower
|
|
||||||
due to a missing library tab image resource. That can be fixed
|
|
||||||
by patching the code that loads the images and ignoring unknown images. -->
|
|
||||||
<item>19.35.36</item>
|
<item>19.35.36</item>
|
||||||
<item>19.26.42</item>
|
<item>19.26.42</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="revanced_spoof_app_version_target_legacy_entries">
|
|
||||||
<item>@string/revanced_spoof_app_version_target_legacy_entry_1</item>
|
|
||||||
<item>@string/revanced_spoof_app_version_target_legacy_entry_2</item>
|
|
||||||
<item>@string/revanced_spoof_app_version_target_legacy_entry_3</item>
|
|
||||||
<item>@string/revanced_spoof_app_version_target_legacy_entry_4</item>
|
|
||||||
</string-array>
|
|
||||||
<string-array name="revanced_spoof_app_version_target_legacy_entry_values">
|
|
||||||
<item>18.33.40</item>
|
|
||||||
<item>18.20.39</item>
|
|
||||||
<item>18.09.39</item>
|
|
||||||
<item>17.33.42</item>
|
|
||||||
</string-array>
|
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="layout.formfactor.changeFormFactorPatch">
|
<patch id="layout.formfactor.changeFormFactorPatch">
|
||||||
<string-array name="revanced_change_form_factor_entries">
|
<string-array name="revanced_change_form_factor_entries">
|
||||||
|
@ -868,7 +868,6 @@ Settings → Playback → Autoplay next video"</string>
|
|||||||
<string name="revanced_ryd_enable_summary_on">Dislikes are shown</string>
|
<string name="revanced_ryd_enable_summary_on">Dislikes are shown</string>
|
||||||
<string name="revanced_ryd_enable_summary_off">Dislikes are not shown</string>
|
<string name="revanced_ryd_enable_summary_off">Dislikes are not shown</string>
|
||||||
<string name="revanced_ryd_shorts_title">Show dislikes on Shorts</string>
|
<string name="revanced_ryd_shorts_title">Show dislikes on Shorts</string>
|
||||||
<string name="revanced_ryd_shorts_summary_on">Dislikes on Shorts are shown</string>
|
|
||||||
<string name="revanced_ryd_shorts_summary_on_disclaimer">"Dislikes on Shorts are shown
|
<string name="revanced_ryd_shorts_summary_on_disclaimer">"Dislikes on Shorts are shown
|
||||||
|
|
||||||
Limitation: Dislikes may not appear in incognito mode"</string>
|
Limitation: Dislikes may not appear in incognito mode"</string>
|
||||||
@ -1157,11 +1156,6 @@ If later turned off, it is recommended to clear the app data to prevent UI bugs.
|
|||||||
<string name="revanced_spoof_app_version_target_title">Spoof app version target</string>
|
<string name="revanced_spoof_app_version_target_title">Spoof app version target</string>
|
||||||
<string name="revanced_spoof_app_version_target_entry_1">19.35.36 - Restore old Shorts player icons</string>
|
<string name="revanced_spoof_app_version_target_entry_1">19.35.36 - Restore old Shorts player icons</string>
|
||||||
<string name="revanced_spoof_app_version_target_entry_2">19.26.42 - Restore old navigation icons</string>
|
<string name="revanced_spoof_app_version_target_entry_2">19.26.42 - Restore old navigation icons</string>
|
||||||
<!-- 'RYD' is 'Return YouTube Dislike' -->
|
|
||||||
<string name="revanced_spoof_app_version_target_legacy_entry_1">18.33.40 - Restore RYD on Shorts incognito mode</string>
|
|
||||||
<string name="revanced_spoof_app_version_target_legacy_entry_2">18.20.39 - Restore wide video speed & quality menu</string>
|
|
||||||
<string name="revanced_spoof_app_version_target_legacy_entry_3">18.09.39 - Restore library tab</string>
|
|
||||||
<string name="revanced_spoof_app_version_target_legacy_entry_4">17.33.42 - Restore old playlist shelf</string>
|
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="layout.startpage.changeStartPagePatch">
|
<patch id="layout.startpage.changeStartPagePatch">
|
||||||
<string name="revanced_change_start_page_title">Set start page</string>
|
<string name="revanced_change_start_page_title">Set start page</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user