mirror of
https://github.com/revanced/revanced-integrations.git
synced 2025-01-04 00:55:49 +01:00
feat(YouTube - Miniplayer): Rename Tablet mini player
and allow selecting the style of the in-app miniplayer (#649)
This commit is contained in:
parent
7a7b2db6f7
commit
f483af6d3a
@ -89,6 +89,7 @@ public class Utils {
|
||||
return versionName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Hide a view by setting its layout height and width to 1dp.
|
||||
*
|
||||
@ -96,11 +97,24 @@ public class Utils {
|
||||
* @param view The view to hide.
|
||||
*/
|
||||
public static void hideViewBy0dpUnderCondition(BooleanSetting condition, View view) {
|
||||
if (!condition.get()) return;
|
||||
if (hideViewBy0dpUnderCondition(condition.get(), view)) {
|
||||
Logger.printDebug(() -> "View hidden by setting: " + condition);
|
||||
}
|
||||
}
|
||||
|
||||
Logger.printDebug(() -> "Hiding view with setting: " + condition);
|
||||
/**
|
||||
* Hide a view by setting its layout height and width to 1dp.
|
||||
*
|
||||
* @param condition The setting to check for hiding the view.
|
||||
* @param view The view to hide.
|
||||
*/
|
||||
public static boolean hideViewBy0dpUnderCondition(boolean condition, View view) {
|
||||
if (condition) {
|
||||
hideViewByLayoutParams(view);
|
||||
return true;
|
||||
}
|
||||
|
||||
hideViewByLayoutParams(view);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,20 +124,42 @@ public class Utils {
|
||||
* @param view The view to hide.
|
||||
*/
|
||||
public static void hideViewUnderCondition(BooleanSetting condition, View view) {
|
||||
if (!condition.get()) return;
|
||||
|
||||
Logger.printDebug(() -> "Hiding view with setting: " + condition);
|
||||
|
||||
view.setVisibility(View.GONE);
|
||||
if (hideViewUnderCondition(condition.get(), view)) {
|
||||
Logger.printDebug(() -> "View hidden by setting: " + condition);
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeViewFromParentUnderConditions(BooleanSetting setting, View view) {
|
||||
if (setting.get()) {
|
||||
/**
|
||||
* Hide a view by setting its visibility to GONE.
|
||||
*
|
||||
* @param condition The setting to check for hiding the view.
|
||||
* @param view The view to hide.
|
||||
*/
|
||||
public static boolean hideViewUnderCondition(boolean condition, View view) {
|
||||
if (condition) {
|
||||
view.setVisibility(View.GONE);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void hideViewByRemovingFromParentUnderCondition(BooleanSetting condition, View view) {
|
||||
if (hideViewByRemovingFromParentUnderCondition(condition.get(), view)) {
|
||||
Logger.printDebug(() -> "View hidden by setting: " + condition);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hideViewByRemovingFromParentUnderCondition(boolean setting, View view) {
|
||||
if (setting) {
|
||||
ViewParent parent = view.getParent();
|
||||
if (parent instanceof ViewGroup) {
|
||||
((ViewGroup) parent).removeView(view);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -236,6 +272,8 @@ public class Utils {
|
||||
@NonNull MatchFilter<View> filter) {
|
||||
for (int i = 0, childCount = viewGroup.getChildCount(); i < childCount; i++) {
|
||||
View childAt = viewGroup.getChildAt(i);
|
||||
Logger.printDebug(() -> "View id: " + childAt.getId() + " tag: " + childAt.getTag());
|
||||
|
||||
if (filter.matches(childAt)) {
|
||||
//noinspection unchecked
|
||||
return (T) childAt;
|
||||
|
@ -2,13 +2,15 @@ package app.revanced.integrations.shared.settings;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import app.revanced.integrations.shared.Logger;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
import app.revanced.integrations.shared.Logger;
|
||||
|
||||
/**
|
||||
* If an Enum value is removed or changed, any saved or imported data using the
|
||||
* non-existent value will be reverted to the default value
|
||||
@ -98,4 +100,18 @@ public class EnumSetting<T extends Enum<?>> extends Setting<T> {
|
||||
public T get() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Availability based on if this setting is currently set to any of the provided types.
|
||||
*/
|
||||
@SafeVarargs
|
||||
public final Setting.Availability availability(@NonNull T... types) {
|
||||
return () -> {
|
||||
T currentEnumType = get();
|
||||
for (T enumType : types) {
|
||||
if (currentEnumType == enumType) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import app.revanced.integrations.tiktok.settings.Settings;
|
||||
@SuppressWarnings("unused")
|
||||
public class SpoofSimPatch {
|
||||
|
||||
private static final Boolean ENABLED = Settings.SIM_SPOOF.get();
|
||||
private static final boolean ENABLED = Settings.SIM_SPOOF.get();
|
||||
|
||||
public static String getCountryIso(String value) {
|
||||
if (ENABLED) {
|
||||
|
@ -1,22 +1,33 @@
|
||||
package app.revanced.integrations.youtube.patches;
|
||||
|
||||
import static app.revanced.integrations.shared.StringRef.str;
|
||||
|
||||
import android.widget.ImageView;
|
||||
|
||||
import app.revanced.integrations.youtube.settings.Settings;
|
||||
import app.revanced.integrations.shared.Utils;
|
||||
import app.revanced.integrations.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class CustomPlayerOverlayOpacityPatch {
|
||||
|
||||
public static void changeOpacity(ImageView imageView) {
|
||||
private static final int PLAYER_OVERLAY_OPACITY_LEVEL;
|
||||
|
||||
static {
|
||||
int opacity = Settings.PLAYER_OVERLAY_OPACITY.get();
|
||||
|
||||
if (opacity < 0 || opacity > 100) {
|
||||
Utils.showToastLong("Player overlay opacity must be between 0-100");
|
||||
Utils.showToastLong(str("revanced_player_overlay_opacity_invalid_toast"));
|
||||
Settings.PLAYER_OVERLAY_OPACITY.resetToDefault();
|
||||
opacity = Settings.PLAYER_OVERLAY_OPACITY.defaultValue;
|
||||
}
|
||||
|
||||
imageView.setImageAlpha((opacity * 255) / 100);
|
||||
PLAYER_OVERLAY_OPACITY_LEVEL = (opacity * 255) / 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void changeOpacity(ImageView imageView) {
|
||||
imageView.setImageAlpha(PLAYER_OVERLAY_OPACITY_LEVEL);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +0,0 @@
|
||||
package app.revanced.integrations.youtube.patches;
|
||||
|
||||
import app.revanced.integrations.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class EnableTabletLayoutPatch {
|
||||
public static boolean enableTabletLayout() {
|
||||
return Settings.TABLET_LAYOUT.get();
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ import app.revanced.integrations.youtube.settings.Settings;
|
||||
@SuppressWarnings("unused")
|
||||
public class HideAutoplayButtonPatch {
|
||||
|
||||
private static final Boolean HIDE_AUTOPLAY_BUTTON_ENABLED = Settings.HIDE_AUTOPLAY_BUTTON.get();
|
||||
private static final boolean HIDE_AUTOPLAY_BUTTON_ENABLED = Settings.HIDE_AUTOPLAY_BUTTON.get();
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
|
@ -0,0 +1,166 @@
|
||||
package app.revanced.integrations.youtube.patches;
|
||||
|
||||
import static app.revanced.integrations.shared.StringRef.str;
|
||||
import static app.revanced.integrations.youtube.patches.MiniplayerPatch.MiniplayerType.*;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.integrations.shared.Logger;
|
||||
import app.revanced.integrations.shared.Utils;
|
||||
import app.revanced.integrations.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class MiniplayerPatch {
|
||||
|
||||
/**
|
||||
* Mini player type. Null fields indicates to use the original un-patched value.
|
||||
*/
|
||||
public enum MiniplayerType {
|
||||
/** Unmodified type, and same as un-patched. */
|
||||
ORIGINAL(null, null),
|
||||
PHONE(false, null),
|
||||
TABLET(true, null),
|
||||
MODERN_1(null, 1),
|
||||
MODERN_2(null, 2),
|
||||
MODERN_3(null, 3);
|
||||
|
||||
/**
|
||||
* Legacy tablet hook value.
|
||||
*/
|
||||
@Nullable
|
||||
final Boolean legacyTabletOverride;
|
||||
|
||||
/**
|
||||
* Modern player type used by YT.
|
||||
*/
|
||||
@Nullable
|
||||
final Integer modernPlayerType;
|
||||
|
||||
MiniplayerType(@Nullable Boolean legacyTabletOverride, @Nullable Integer modernPlayerType) {
|
||||
this.legacyTabletOverride = legacyTabletOverride;
|
||||
this.modernPlayerType = modernPlayerType;
|
||||
}
|
||||
|
||||
public boolean isModern() {
|
||||
return modernPlayerType != null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Modern subtitle overlay for {@link MiniplayerType#MODERN_2}.
|
||||
* Resource is not present in older targets, and this field will be zero.
|
||||
*/
|
||||
private static final int MODERN_OVERLAY_SUBTITLE_TEXT
|
||||
= Utils.getResourceIdentifier("modern_miniplayer_subtitle_text", "id");
|
||||
|
||||
private static final MiniplayerType CURRENT_TYPE = Settings.MINIPLAYER_TYPE.get();
|
||||
|
||||
private static final boolean HIDE_EXPAND_CLOSE_ENABLED =
|
||||
(CURRENT_TYPE == MODERN_1 || CURRENT_TYPE == MODERN_3) && Settings.MINIPLAYER_HIDE_EXPAND_CLOSE.get();
|
||||
|
||||
private static final boolean HIDE_SUBTEXT_ENABLED =
|
||||
(CURRENT_TYPE == MODERN_1 || CURRENT_TYPE == MODERN_3) && Settings.MINIPLAYER_HIDE_SUBTEXT.get();
|
||||
|
||||
private static final boolean HIDE_REWIND_FORWARD_ENABLED =
|
||||
CURRENT_TYPE == MODERN_1 && Settings.MINIPLAYER_HIDE_REWIND_FORWARD.get();
|
||||
|
||||
private static final int OPACITY_LEVEL;
|
||||
|
||||
static {
|
||||
int opacity = Settings.MINIPLAYER_OPACITY.get();
|
||||
|
||||
if (opacity < 0 || opacity > 100) {
|
||||
Utils.showToastLong(str("revanced_miniplayer_opacity_invalid_toast"));
|
||||
Settings.MINIPLAYER_OPACITY.resetToDefault();
|
||||
opacity = Settings.MINIPLAYER_OPACITY.defaultValue;
|
||||
}
|
||||
|
||||
OPACITY_LEVEL = (opacity * 255) / 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean getLegacyTabletMiniplayerOverride(boolean original) {
|
||||
Boolean isTablet = CURRENT_TYPE.legacyTabletOverride;
|
||||
return isTablet == null
|
||||
? original
|
||||
: isTablet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean getModernMiniplayerOverride(boolean original) {
|
||||
return CURRENT_TYPE == ORIGINAL
|
||||
? original
|
||||
: CURRENT_TYPE.isModern();
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static int getModernMiniplayerOverrideType(int original) {
|
||||
Integer modernValue = CURRENT_TYPE.modernPlayerType;
|
||||
return modernValue == null
|
||||
? original
|
||||
: modernValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void adjustMiniplayerOpacity(ImageView view) {
|
||||
if (CURRENT_TYPE == MODERN_1) {
|
||||
view.setImageAlpha(OPACITY_LEVEL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void hideMiniplayerExpandClose(ImageView view) {
|
||||
Utils.hideViewByRemovingFromParentUnderCondition(HIDE_EXPAND_CLOSE_ENABLED, view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void hideMiniplayerRewindForward(ImageView view) {
|
||||
Utils.hideViewByRemovingFromParentUnderCondition(HIDE_REWIND_FORWARD_ENABLED, view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void hideMiniplayerSubTexts(View view) {
|
||||
// Different subviews are passed in, but only TextView and layouts are of interest here.
|
||||
final boolean hideView = HIDE_SUBTEXT_ENABLED && (view instanceof TextView || view instanceof LinearLayout);
|
||||
Utils.hideViewByRemovingFromParentUnderCondition(hideView, view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void playerOverlayGroupCreated(View group) {
|
||||
// Modern 2 has an half broken subtitle that is always present.
|
||||
// Always hide it to make the miniplayer mostly usable.
|
||||
if (CURRENT_TYPE == MODERN_2 && 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@ public final class NavigationButtonsPatch {
|
||||
}
|
||||
};
|
||||
|
||||
private static final Boolean SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON
|
||||
private static final boolean SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON
|
||||
= Settings.SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON.get();
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,16 @@
|
||||
package app.revanced.integrations.youtube.patches;
|
||||
|
||||
import app.revanced.integrations.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class TabletLayoutPatch {
|
||||
|
||||
private static final boolean TABLET_LAYOUT_ENABLED = Settings.TABLET_LAYOUT.get();
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean getTabletLayoutEnabled() {
|
||||
return TABLET_LAYOUT_ENABLED;
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package app.revanced.integrations.youtube.patches;
|
||||
|
||||
import app.revanced.integrations.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class TabletMiniPlayerOverridePatch {
|
||||
|
||||
public static boolean getTabletMiniPlayerOverride(boolean original) {
|
||||
if (Settings.USE_TABLET_MINIPLAYER.get())
|
||||
return true;
|
||||
return original;
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package app.revanced.integrations.youtube.patches.components;
|
||||
|
||||
import static app.revanced.integrations.shared.Utils.hideViewUnderCondition;
|
||||
import static app.revanced.integrations.shared.Utils.removeViewFromParentUnderConditions;
|
||||
import static app.revanced.integrations.youtube.shared.NavigationBar.NavigationButton;
|
||||
|
||||
import android.view.View;
|
||||
@ -326,11 +325,11 @@ public final class ShortsFilter extends Filter {
|
||||
// the button was (only relevant for dislikes button).
|
||||
//
|
||||
// Instead remove the view from the parent.
|
||||
removeViewFromParentUnderConditions(Settings.HIDE_SHORTS_LIKE_BUTTON, likeButtonView);
|
||||
Utils.hideViewByRemovingFromParentUnderCondition(Settings.HIDE_SHORTS_LIKE_BUTTON, likeButtonView);
|
||||
}
|
||||
|
||||
public static void hideDislikeButton(final View dislikeButtonView) {
|
||||
removeViewFromParentUnderConditions(Settings.HIDE_SHORTS_DISLIKE_BUTTON, dislikeButtonView);
|
||||
Utils.hideViewByRemovingFromParentUnderCondition(Settings.HIDE_SHORTS_DISLIKE_BUTTON, dislikeButtonView);
|
||||
}
|
||||
|
||||
public static void hideShortsCommentsButton(final View commentsButtonView) {
|
||||
|
@ -1,5 +1,17 @@
|
||||
package app.revanced.integrations.youtube.settings;
|
||||
|
||||
import static java.lang.Boolean.FALSE;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static app.revanced.integrations.shared.settings.Setting.*;
|
||||
import static app.revanced.integrations.youtube.patches.MiniplayerPatch.MiniplayerType;
|
||||
import static app.revanced.integrations.youtube.patches.MiniplayerPatch.MiniplayerType.MODERN_1;
|
||||
import static app.revanced.integrations.youtube.patches.MiniplayerPatch.MiniplayerType.MODERN_3;
|
||||
import static app.revanced.integrations.youtube.sponsorblock.objects.CategoryBehaviour.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import app.revanced.integrations.shared.Logger;
|
||||
import app.revanced.integrations.shared.settings.*;
|
||||
import app.revanced.integrations.shared.settings.preference.SharedPrefCategory;
|
||||
@ -10,15 +22,7 @@ import app.revanced.integrations.youtube.patches.AlternativeThumbnailsPatch.Thum
|
||||
import app.revanced.integrations.youtube.patches.spoof.SpoofAppVersionPatch;
|
||||
import app.revanced.integrations.youtube.sponsorblock.SponsorBlockSettings;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static app.revanced.integrations.shared.settings.Setting.*;
|
||||
import static app.revanced.integrations.youtube.sponsorblock.objects.CategoryBehaviour.*;
|
||||
import static java.lang.Boolean.FALSE;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class Settings extends BaseSettings {
|
||||
// Video
|
||||
public static final BooleanSetting RESTORE_OLD_VIDEO_QUALITY_MENU = new BooleanSetting("revanced_restore_old_video_quality_menu", TRUE);
|
||||
@ -129,6 +133,13 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting COPY_VIDEO_URL_TIMESTAMP = new BooleanSetting("revanced_copy_video_url_timestamp", TRUE);
|
||||
public static final BooleanSetting PLAYBACK_SPEED_DIALOG_BUTTON = new BooleanSetting("revanced_playback_speed_dialog_button", FALSE);
|
||||
|
||||
// Miniplayer
|
||||
public static final EnumSetting<MiniplayerType> MINIPLAYER_TYPE = new EnumSetting<>("revanced_miniplayer_type", MiniplayerType.ORIGINAL, true);
|
||||
public static final BooleanSetting MINIPLAYER_HIDE_EXPAND_CLOSE = new BooleanSetting("revanced_miniplayer_hide_expand_close", FALSE, true, MINIPLAYER_TYPE.availability(MODERN_1, MODERN_3));
|
||||
public static final BooleanSetting MINIPLAYER_HIDE_SUBTEXT = new BooleanSetting("revanced_miniplayer_hide_subtext", FALSE, true, MINIPLAYER_TYPE.availability(MODERN_1, MODERN_3));
|
||||
public static final BooleanSetting MINIPLAYER_HIDE_REWIND_FORWARD = new BooleanSetting("revanced_miniplayer_hide_rewind_forward", FALSE, true, MINIPLAYER_TYPE.availability(MODERN_1));
|
||||
public static final IntegerSetting MINIPLAYER_OPACITY = new IntegerSetting("revanced_miniplayer_opacity", 100, true, MINIPLAYER_TYPE.availability(MODERN_1));
|
||||
|
||||
// External downloader
|
||||
public static final BooleanSetting EXTERNAL_DOWNLOADER = new BooleanSetting("revanced_external_downloader", FALSE);
|
||||
public static final BooleanSetting EXTERNAL_DOWNLOADER_ACTION_BUTTON = new BooleanSetting("revanced_external_downloader_action_button", FALSE);
|
||||
@ -175,7 +186,6 @@ 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 StringSetting SPOOF_APP_VERSION_TARGET = new StringSetting("revanced_spoof_app_version_target", "17.33.42", true, parent(SPOOF_APP_VERSION));
|
||||
public static final BooleanSetting TABLET_LAYOUT = new BooleanSetting("revanced_tablet_layout", FALSE, true, "revanced_tablet_layout_user_dialog_message");
|
||||
public static final BooleanSetting USE_TABLET_MINIPLAYER = new BooleanSetting("revanced_tablet_miniplayer", FALSE, true);
|
||||
public static final BooleanSetting WIDE_SEARCHBAR = new BooleanSetting("revanced_wide_searchbar", FALSE, true);
|
||||
public static final BooleanSetting REMOVE_VIEWER_DISCRETION_DIALOG = new BooleanSetting("revanced_remove_viewer_discretion_dialog", FALSE,
|
||||
"revanced_remove_viewer_discretion_dialog_user_dialog_message");
|
||||
|
Loading…
Reference in New Issue
Block a user