mirror of
https://github.com/revanced/revanced-patches
synced 2025-01-16 14:17:34 +01:00
feat(YouTube): Add Change form factor
patch (#4217)
This commit is contained in:
parent
da4aeac42b
commit
644ac5baa6
@ -153,7 +153,6 @@ public abstract class Setting<T> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Confirmation message to display, if the user tries to change the setting from the default value.
|
* Confirmation message to display, if the user tries to change the setting from the default value.
|
||||||
* Currently this works only for Boolean setting types.
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public final StringRef userDialogMessage;
|
public final StringRef userDialogMessage;
|
||||||
@ -244,6 +243,7 @@ public abstract class Setting<T> {
|
|||||||
*
|
*
|
||||||
* This method will be deleted in the future.
|
* This method will be deleted in the future.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
public static void migrateFromOldPreferences(@NonNull SharedPrefCategory oldPrefs, @NonNull Setting setting, String settingKey) {
|
public static void migrateFromOldPreferences(@NonNull SharedPrefCategory oldPrefs, @NonNull Setting setting, String settingKey) {
|
||||||
if (!oldPrefs.preferences.contains(settingKey)) {
|
if (!oldPrefs.preferences.contains(settingKey)) {
|
||||||
return; // Nothing to do.
|
return; // Nothing to do.
|
||||||
@ -419,6 +419,7 @@ public abstract class Setting<T> {
|
|||||||
|
|
||||||
boolean rebootSettingChanged = false;
|
boolean rebootSettingChanged = false;
|
||||||
int numberOfSettingsImported = 0;
|
int numberOfSettingsImported = 0;
|
||||||
|
//noinspection rawtypes
|
||||||
for (Setting setting : SETTINGS) {
|
for (Setting setting : SETTINGS) {
|
||||||
String key = setting.getImportExportKey();
|
String key = setting.getImportExportKey();
|
||||||
if (json.has(key)) {
|
if (json.has(key)) {
|
||||||
|
@ -42,7 +42,7 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
|||||||
|
|
||||||
private final SharedPreferences.OnSharedPreferenceChangeListener listener = (sharedPreferences, str) -> {
|
private final SharedPreferences.OnSharedPreferenceChangeListener listener = (sharedPreferences, str) -> {
|
||||||
try {
|
try {
|
||||||
Setting<?> setting = Setting.getSettingFromPath(str);
|
Setting<?> setting = Setting.getSettingFromPath(Objects.requireNonNull(str));
|
||||||
if (setting == null) {
|
if (setting == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -52,23 +52,21 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
|||||||
}
|
}
|
||||||
Logger.printDebug(() -> "Preference changed: " + setting.key);
|
Logger.printDebug(() -> "Preference changed: " + setting.key);
|
||||||
|
|
||||||
// Apply 'Setting <- Preference', unless during importing when it needs to be 'Setting -> Preference'.
|
if (!settingImportInProgress && !showingUserDialogMessage) {
|
||||||
updatePreference(pref, setting, true, settingImportInProgress);
|
if (setting.userDialogMessage != null && !prefIsSetToDefault(pref, setting)) {
|
||||||
// Update any other preference availability that may now be different.
|
// Do not change the setting yet, to allow preserving whatever
|
||||||
updateUIAvailability();
|
// list/text value was previously set if it needs to be reverted.
|
||||||
|
showSettingUserDialogConfirmation(pref, setting);
|
||||||
if (settingImportInProgress) {
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!showingUserDialogMessage) {
|
|
||||||
if (setting.userDialogMessage != null && ((SwitchPreference) pref).isChecked() != (Boolean) setting.defaultValue) {
|
|
||||||
showSettingUserDialogConfirmation((SwitchPreference) pref, (BooleanSetting) setting);
|
|
||||||
} else if (setting.rebootApp) {
|
} else if (setting.rebootApp) {
|
||||||
showRestartDialog(getContext());
|
showRestartDialog(getContext());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply 'Setting <- Preference', unless during importing when it needs to be 'Setting -> Preference'.
|
||||||
|
updatePreference(pref, setting, true, settingImportInProgress);
|
||||||
|
// Update any other preference availability that may now be different.
|
||||||
|
updateUIAvailability();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.printException(() -> "OnSharedPreferenceChangeListener failure", ex);
|
Logger.printException(() -> "OnSharedPreferenceChangeListener failure", ex);
|
||||||
}
|
}
|
||||||
@ -92,7 +90,7 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
|||||||
Utils.setPreferenceTitlesToMultiLineIfNeeded(screen);
|
Utils.setPreferenceTitlesToMultiLineIfNeeded(screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showSettingUserDialogConfirmation(SwitchPreference switchPref, BooleanSetting setting) {
|
private void showSettingUserDialogConfirmation(Preference pref, Setting<?> setting) {
|
||||||
Utils.verifyOnMainThread();
|
Utils.verifyOnMainThread();
|
||||||
|
|
||||||
final var context = getContext();
|
final var context = getContext();
|
||||||
@ -104,12 +102,19 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
|||||||
.setTitle(confirmDialogTitle)
|
.setTitle(confirmDialogTitle)
|
||||||
.setMessage(Objects.requireNonNull(setting.userDialogMessage).toString())
|
.setMessage(Objects.requireNonNull(setting.userDialogMessage).toString())
|
||||||
.setPositiveButton(android.R.string.ok, (dialog, id) -> {
|
.setPositiveButton(android.R.string.ok, (dialog, id) -> {
|
||||||
|
// User confirmed, save to the Setting.
|
||||||
|
updatePreference(pref, setting, true, false);
|
||||||
|
|
||||||
|
// Update availability of other preferences that may be changed.
|
||||||
|
updateUIAvailability();
|
||||||
|
|
||||||
if (setting.rebootApp) {
|
if (setting.rebootApp) {
|
||||||
showRestartDialog(context);
|
showRestartDialog(context);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.setNegativeButton(android.R.string.cancel, (dialog, id) -> {
|
.setNegativeButton(android.R.string.cancel, (dialog, id) -> {
|
||||||
switchPref.setChecked(setting.defaultValue); // Recursive call that resets the Setting value.
|
// Restore whatever the setting was before the change.
|
||||||
|
updatePreference(pref, setting, true, true);
|
||||||
})
|
})
|
||||||
.setOnDismissListener(dialog -> {
|
.setOnDismissListener(dialog -> {
|
||||||
showingUserDialogMessage = false;
|
showingUserDialogMessage = false;
|
||||||
@ -132,6 +137,24 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
|||||||
updatePreferenceScreen(getPreferenceScreen(), false, false);
|
updatePreferenceScreen(getPreferenceScreen(), false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return If the preference is currently set to the default value of the Setting.
|
||||||
|
*/
|
||||||
|
protected boolean prefIsSetToDefault(Preference pref, Setting<?> setting) {
|
||||||
|
if (pref instanceof SwitchPreference switchPref) {
|
||||||
|
return switchPref.isChecked() == (Boolean) setting.defaultValue;
|
||||||
|
}
|
||||||
|
if (pref instanceof EditTextPreference editPreference) {
|
||||||
|
return editPreference.getText().equals(setting.defaultValue.toString());
|
||||||
|
}
|
||||||
|
if (pref instanceof ListPreference listPref) {
|
||||||
|
return listPref.getValue().equals(setting.defaultValue.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Must override method to handle "
|
||||||
|
+ "preference type: " + pref.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Syncs all UI Preferences to any {@link Setting} they represent.
|
* Syncs all UI Preferences to any {@link Setting} they represent.
|
||||||
*/
|
*/
|
||||||
@ -170,23 +193,20 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
|||||||
protected void syncSettingWithPreference(@NonNull Preference pref,
|
protected void syncSettingWithPreference(@NonNull Preference pref,
|
||||||
@NonNull Setting<?> setting,
|
@NonNull Setting<?> setting,
|
||||||
boolean applySettingToPreference) {
|
boolean applySettingToPreference) {
|
||||||
if (pref instanceof SwitchPreference) {
|
if (pref instanceof SwitchPreference switchPref) {
|
||||||
SwitchPreference switchPref = (SwitchPreference) pref;
|
|
||||||
BooleanSetting boolSetting = (BooleanSetting) setting;
|
BooleanSetting boolSetting = (BooleanSetting) setting;
|
||||||
if (applySettingToPreference) {
|
if (applySettingToPreference) {
|
||||||
switchPref.setChecked(boolSetting.get());
|
switchPref.setChecked(boolSetting.get());
|
||||||
} else {
|
} else {
|
||||||
BooleanSetting.privateSetValue(boolSetting, switchPref.isChecked());
|
BooleanSetting.privateSetValue(boolSetting, switchPref.isChecked());
|
||||||
}
|
}
|
||||||
} else if (pref instanceof EditTextPreference) {
|
} else if (pref instanceof EditTextPreference editPreference) {
|
||||||
EditTextPreference editPreference = (EditTextPreference) pref;
|
|
||||||
if (applySettingToPreference) {
|
if (applySettingToPreference) {
|
||||||
editPreference.setText(setting.get().toString());
|
editPreference.setText(setting.get().toString());
|
||||||
} else {
|
} else {
|
||||||
Setting.privateSetValueFromString(setting, editPreference.getText());
|
Setting.privateSetValueFromString(setting, editPreference.getText());
|
||||||
}
|
}
|
||||||
} else if (pref instanceof ListPreference) {
|
} else if (pref instanceof ListPreference listPref) {
|
||||||
ListPreference listPref = (ListPreference) pref;
|
|
||||||
if (applySettingToPreference) {
|
if (applySettingToPreference) {
|
||||||
listPref.setValue(setting.get().toString());
|
listPref.setValue(setting.get().toString());
|
||||||
} else {
|
} else {
|
||||||
|
@ -176,14 +176,13 @@ public final class AlternativeThumbnailsPatch {
|
|||||||
// Unknown tab, treat as the home tab;
|
// Unknown tab, treat as the home tab;
|
||||||
return homeOption;
|
return homeOption;
|
||||||
}
|
}
|
||||||
if (selectedNavButton == NavigationButton.HOME) {
|
|
||||||
return homeOption;
|
return switch (selectedNavButton) {
|
||||||
}
|
case SUBSCRIPTIONS, NOTIFICATIONS -> subscriptionsOption;
|
||||||
if (selectedNavButton == NavigationButton.SUBSCRIPTIONS || selectedNavButton == NavigationButton.NOTIFICATIONS) {
|
case LIBRARY -> libraryOption;
|
||||||
return subscriptionsOption;
|
// Home or explore tab.
|
||||||
}
|
default -> homeOption;
|
||||||
// A library tab variant is active.
|
};
|
||||||
return libraryOption;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
package app.revanced.extension.youtube.patches;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import app.revanced.extension.shared.Utils;
|
||||||
|
import app.revanced.extension.youtube.settings.Settings;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class ChangeFormFactorPatch {
|
||||||
|
|
||||||
|
public enum FormFactor {
|
||||||
|
/**
|
||||||
|
* Unmodified, and same as un-patched.
|
||||||
|
*/
|
||||||
|
DEFAULT(null),
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* Some changes include:
|
||||||
|
* - Explore tab is present.
|
||||||
|
* - watch history is missing.
|
||||||
|
* - feed thumbnails fade in.
|
||||||
|
*/
|
||||||
|
UNKNOWN(0),
|
||||||
|
SMALL(1),
|
||||||
|
LARGE(2),
|
||||||
|
/**
|
||||||
|
* Cars with 'Google built-in'.
|
||||||
|
* Layout seems identical to {@link #UNKNOWN}
|
||||||
|
* even when using an Android Automotive device.
|
||||||
|
*/
|
||||||
|
AUTOMOTIVE(3),
|
||||||
|
WEARABLE(4);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
final Integer formFactorType;
|
||||||
|
|
||||||
|
FormFactor(@Nullable Integer formFactorType) {
|
||||||
|
this.formFactorType = formFactorType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static final Integer FORM_FACTOR_TYPE = Settings.CHANGE_FORM_FACTOR.get().formFactorType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point.
|
||||||
|
*/
|
||||||
|
public static int getFormFactor(int original) {
|
||||||
|
return FORM_FACTOR_TYPE == null
|
||||||
|
? original
|
||||||
|
: FORM_FACTOR_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,16 +0,0 @@
|
|||||||
package app.revanced.extension.youtube.patches;
|
|
||||||
|
|
||||||
import app.revanced.extension.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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -528,14 +528,13 @@ final class KeywordContentFilter extends Filter {
|
|||||||
if (selectedNavButton == null) {
|
if (selectedNavButton == null) {
|
||||||
return hideHome; // Unknown tab, treat the same as home.
|
return hideHome; // Unknown tab, treat the same as home.
|
||||||
}
|
}
|
||||||
if (selectedNavButton == NavigationButton.HOME) {
|
|
||||||
return hideHome;
|
return switch (selectedNavButton) {
|
||||||
}
|
case HOME, EXPLORE -> hideHome;
|
||||||
if (selectedNavButton == NavigationButton.SUBSCRIPTIONS) {
|
case SUBSCRIPTIONS -> hideSubscriptions;
|
||||||
return hideSubscriptions;
|
// User is in the Library or notifications.
|
||||||
}
|
default -> false;
|
||||||
// User is in the Library or Notifications tab.
|
};
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateStats(boolean videoWasHidden, @Nullable String keyword) {
|
private void updateStats(boolean videoWasHidden, @Nullable String keyword) {
|
||||||
|
@ -366,7 +366,7 @@ public final class ShortsFilter extends Filter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return switch (selectedNavButton) {
|
return switch (selectedNavButton) {
|
||||||
case HOME -> hideHome;
|
case HOME, EXPLORE -> hideHome;
|
||||||
case SUBSCRIPTIONS -> hideSubscriptions;
|
case SUBSCRIPTIONS -> hideSubscriptions;
|
||||||
case LIBRARY -> hideHistory;
|
case LIBRARY -> hideHistory;
|
||||||
default -> false;
|
default -> false;
|
||||||
|
@ -7,6 +7,7 @@ import static app.revanced.extension.shared.settings.Setting.migrateFromOldPrefe
|
|||||||
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;
|
||||||
|
import static app.revanced.extension.youtube.patches.ChangeFormFactorPatch.FormFactor;
|
||||||
import static app.revanced.extension.youtube.patches.ChangeStartPagePatch.StartPage;
|
import static app.revanced.extension.youtube.patches.ChangeStartPagePatch.StartPage;
|
||||||
import static app.revanced.extension.youtube.patches.ExitFullscreenPatch.FullscreenMode;
|
import static app.revanced.extension.youtube.patches.ExitFullscreenPatch.FullscreenMode;
|
||||||
import static app.revanced.extension.youtube.patches.ForceOriginalAudioPatch.ForceOriginalAudioAvailability;
|
import static app.revanced.extension.youtube.patches.ForceOriginalAudioPatch.ForceOriginalAudioAvailability;
|
||||||
@ -202,12 +203,12 @@ public class Settings extends BaseSettings {
|
|||||||
public static final BooleanSetting HIDE_PLAYER_FLYOUT_WATCH_IN_VR = new BooleanSetting("revanced_hide_player_flyout_watch_in_vr", TRUE);
|
public static final BooleanSetting HIDE_PLAYER_FLYOUT_WATCH_IN_VR = new BooleanSetting("revanced_hide_player_flyout_watch_in_vr", TRUE);
|
||||||
|
|
||||||
// General layout
|
// General layout
|
||||||
|
public static final EnumSetting<FormFactor> CHANGE_FORM_FACTOR = new EnumSetting<>("revanced_change_form_factor", FormFactor.DEFAULT, true, "revanced_change_form_factor_user_dialog_message");
|
||||||
public static final BooleanSetting BYPASS_IMAGE_REGION_RESTRICTIONS = new BooleanSetting("revanced_bypass_image_region_restrictions", FALSE, true);
|
public static final BooleanSetting BYPASS_IMAGE_REGION_RESTRICTIONS = new BooleanSetting("revanced_bypass_image_region_restrictions", FALSE, true);
|
||||||
public static final BooleanSetting GRADIENT_LOADING_SCREEN = new BooleanSetting("revanced_gradient_loading_screen", FALSE, true);
|
public static final BooleanSetting GRADIENT_LOADING_SCREEN = new BooleanSetting("revanced_gradient_loading_screen", FALSE, true);
|
||||||
public static final BooleanSetting REMOVE_VIEWER_DISCRETION_DIALOG = new BooleanSetting("revanced_remove_viewer_discretion_dialog", FALSE,
|
public static final BooleanSetting REMOVE_VIEWER_DISCRETION_DIALOG = new BooleanSetting("revanced_remove_viewer_discretion_dialog", FALSE,
|
||||||
"revanced_remove_viewer_discretion_dialog_user_dialog_message");
|
"revanced_remove_viewer_discretion_dialog_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 SPOOF_APP_VERSION = new BooleanSetting("revanced_spoof_app_version", FALSE, true, "revanced_spoof_app_version_user_dialog_message");
|
||||||
public static final BooleanSetting TABLET_LAYOUT = new BooleanSetting("revanced_tablet_layout", FALSE, true, "revanced_tablet_layout_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", IS_19_17_OR_GREATER ? "19.26.42" : "17.33.42", true, parent(SPOOF_APP_VERSION));
|
||||||
|
@ -3,12 +3,15 @@ package app.revanced.extension.youtube.shared;
|
|||||||
import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButton.CREATE;
|
import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButton.CREATE;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.os.Build;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.EnumMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
@ -242,6 +245,30 @@ public final class NavigationBar {
|
|||||||
// Code is added during patching.
|
// Code is added during patching.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use the bundled non cairo filled icon instead of a custom icon.
|
||||||
|
* Use the old non cairo filled icon, which is almost identical to
|
||||||
|
* the what would be the filled cairo icon.
|
||||||
|
*/
|
||||||
|
private static final int fillBellCairoBlack = Utils.getResourceIdentifier(
|
||||||
|
"yt_fill_bell_black_24", "drawable");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point.
|
||||||
|
* Fixes missing drawable.
|
||||||
|
*/
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||||
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
|
public static void setCairoNotificationFilledIcon(EnumMap enumMap, Enum tabActivityCairo) {
|
||||||
|
if (fillBellCairoBlack != 0) {
|
||||||
|
// Show a popup informing this fix is no longer needed to those who might care.
|
||||||
|
if (BaseSettings.DEBUG.get() && enumMap.containsKey(tabActivityCairo)) {
|
||||||
|
Logger.printException(() -> "YouTube fixed the cairo notification icons");
|
||||||
|
}
|
||||||
|
enumMap.putIfAbsent(tabActivityCairo, fillBellCairoBlack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public enum NavigationButton {
|
public enum NavigationButton {
|
||||||
HOME("PIVOT_HOME", "TAB_HOME_CAIRO"),
|
HOME("PIVOT_HOME", "TAB_HOME_CAIRO"),
|
||||||
SHORTS("TAB_SHORTS", "TAB_SHORTS_CAIRO"),
|
SHORTS("TAB_SHORTS", "TAB_SHORTS_CAIRO"),
|
||||||
@ -250,6 +277,10 @@ public final class NavigationBar {
|
|||||||
* This tab will never be in a selected state, even if the create video UI is on screen.
|
* This tab will never be in a selected state, even if the create video UI is on screen.
|
||||||
*/
|
*/
|
||||||
CREATE("CREATION_TAB_LARGE", "CREATION_TAB_LARGE_CAIRO"),
|
CREATE("CREATION_TAB_LARGE", "CREATION_TAB_LARGE_CAIRO"),
|
||||||
|
/**
|
||||||
|
* Only shown to automotive layout.
|
||||||
|
*/
|
||||||
|
EXPLORE("TAB_EXPLORE"),
|
||||||
SUBSCRIPTIONS("PIVOT_SUBSCRIPTIONS", "TAB_SUBSCRIPTIONS_CAIRO"),
|
SUBSCRIPTIONS("PIVOT_SUBSCRIPTIONS", "TAB_SUBSCRIPTIONS_CAIRO"),
|
||||||
/**
|
/**
|
||||||
* Notifications tab. Only present when
|
* Notifications tab. Only present when
|
||||||
|
@ -1101,6 +1101,10 @@ public final class app/revanced/patches/youtube/layout/buttons/overlay/HidePlaye
|
|||||||
public static final fun getHidePlayerOverlayButtonsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getHidePlayerOverlayButtonsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/youtube/layout/formfactor/ChangeFormFactorPatchKt {
|
||||||
|
public static final fun getChangeFormFactorPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsPatchKt {
|
public final class app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsPatchKt {
|
||||||
public static final fun getHideEndscreenCardsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getHideEndscreenCardsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
@ -1230,7 +1234,6 @@ public final class app/revanced/patches/youtube/layout/startupshortsreset/Disabl
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/youtube/layout/tablet/EnableTabletLayoutPatchKt {
|
public final class app/revanced/patches/youtube/layout/tablet/EnableTabletLayoutPatchKt {
|
||||||
public static final field EXTENSION_CLASS_DESCRIPTOR Ljava/lang/String;
|
|
||||||
public static final fun getEnableTabletLayoutPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getEnableTabletLayoutPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.formfactor
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
|
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.youtube.misc.extension.sharedExtensionPatch
|
||||||
|
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||||
|
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||||
|
|
||||||
|
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/ChangeFormFactorPatch;"
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val changeFormFactorPatch = bytecodePatch(
|
||||||
|
name = "Change form factor",
|
||||||
|
description = "Adds an option to change the UI appearance to a phone, tablet, or automotive device.",
|
||||||
|
) {
|
||||||
|
dependsOn(
|
||||||
|
sharedExtensionPatch,
|
||||||
|
settingsPatch,
|
||||||
|
addResourcesPatch,
|
||||||
|
)
|
||||||
|
|
||||||
|
compatibleWith(
|
||||||
|
"com.google.android.youtube"(
|
||||||
|
"18.38.44",
|
||||||
|
"18.49.37",
|
||||||
|
"19.16.39",
|
||||||
|
"19.25.37",
|
||||||
|
"19.34.42",
|
||||||
|
"19.43.41",
|
||||||
|
"19.45.38",
|
||||||
|
"19.46.42",
|
||||||
|
"19.47.53",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
execute {
|
||||||
|
addResources("youtube", "layout.formfactor.changeFormFactorPatch")
|
||||||
|
|
||||||
|
PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||||
|
ListPreference(
|
||||||
|
"revanced_change_form_factor",
|
||||||
|
summaryKey = null,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
createPlayerRequestBodyWithModelFingerprint.method.apply {
|
||||||
|
val formFactorEnumClass = formFactorEnumConstructorFingerprint.originalClassDef.type
|
||||||
|
|
||||||
|
val index = indexOfFirstInstructionOrThrow {
|
||||||
|
val reference = getReference<FieldReference>()
|
||||||
|
opcode == Opcode.IGET &&
|
||||||
|
reference?.definingClass == formFactorEnumClass &&
|
||||||
|
reference.type == "I"
|
||||||
|
}
|
||||||
|
val register = getInstruction<TwoRegisterInstruction>(index).registerA
|
||||||
|
|
||||||
|
addInstructions(
|
||||||
|
index + 1,
|
||||||
|
"""
|
||||||
|
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getFormFactor(I)I
|
||||||
|
move-result v$register
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.formfactor
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import app.revanced.util.indexOfFirstInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.Method
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||||
|
|
||||||
|
internal val formFactorEnumConstructorFingerprint = fingerprint {
|
||||||
|
accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)
|
||||||
|
strings(
|
||||||
|
"UNKNOWN_FORM_FACTOR",
|
||||||
|
"SMALL_FORM_FACTOR",
|
||||||
|
"LARGE_FORM_FACTOR",
|
||||||
|
"AUTOMOTIVE_FORM_FACTOR"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val createPlayerRequestBodyWithModelFingerprint = fingerprint {
|
||||||
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
|
returns("L")
|
||||||
|
parameters()
|
||||||
|
opcodes(Opcode.OR_INT_LIT16)
|
||||||
|
custom { method, _ ->
|
||||||
|
method.indexOfModelInstruction() >= 0 &&
|
||||||
|
method.indexOfReleaseInstruction() >= 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Method.indexOfModelInstruction() =
|
||||||
|
indexOfFirstInstruction {
|
||||||
|
val reference = getReference<FieldReference>()
|
||||||
|
|
||||||
|
reference?.definingClass == "Landroid/os/Build;" &&
|
||||||
|
reference.name == "MODEL" &&
|
||||||
|
reference.type == "Ljava/lang/String;"
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun Method.indexOfReleaseInstruction(): Int =
|
||||||
|
indexOfFirstInstruction {
|
||||||
|
val reference = getReference<FieldReference>()
|
||||||
|
|
||||||
|
reference?.definingClass == "Landroid/os/Build${'$'}VERSION;" &&
|
||||||
|
reference.name == "RELEASE" &&
|
||||||
|
reference.type == "Ljava/lang/String;"
|
||||||
|
}
|
||||||
|
|
@ -1,66 +1,9 @@
|
|||||||
package app.revanced.patches.youtube.layout.tablet
|
package app.revanced.patches.youtube.layout.tablet
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
import app.revanced.patches.youtube.layout.formfactor.changeFormFactorPatch
|
||||||
import app.revanced.patches.all.misc.resources.addResources
|
|
||||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
|
||||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
|
||||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
|
||||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
|
||||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
|
||||||
|
|
||||||
const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/TabletLayoutPatch;"
|
@Deprecated("Use 'Change form factor' instead.")
|
||||||
|
val enableTabletLayoutPatch = bytecodePatch {
|
||||||
val enableTabletLayoutPatch = bytecodePatch(
|
dependsOn(changeFormFactorPatch)
|
||||||
name = "Enable tablet layout",
|
}
|
||||||
description = "Adds an option to enable tablet layout.",
|
|
||||||
) {
|
|
||||||
dependsOn(
|
|
||||||
sharedExtensionPatch,
|
|
||||||
settingsPatch,
|
|
||||||
addResourcesPatch,
|
|
||||||
)
|
|
||||||
|
|
||||||
compatibleWith(
|
|
||||||
"com.google.android.youtube"(
|
|
||||||
"18.38.44",
|
|
||||||
"18.49.37",
|
|
||||||
"19.16.39",
|
|
||||||
"19.25.37",
|
|
||||||
"19.34.42",
|
|
||||||
"19.43.41",
|
|
||||||
"19.45.38",
|
|
||||||
"19.46.42",
|
|
||||||
"19.47.53",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
execute {
|
|
||||||
addResources("youtube", "layout.tablet.enableTabletLayoutPatch")
|
|
||||||
|
|
||||||
PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
|
||||||
SwitchPreference("revanced_tablet_layout"),
|
|
||||||
)
|
|
||||||
|
|
||||||
getFormFactorFingerprint.method.apply {
|
|
||||||
val returnIsLargeFormFactorIndex = instructions.lastIndex - 4
|
|
||||||
val returnIsLargeFormFactorLabel = getInstruction(returnIsLargeFormFactorIndex)
|
|
||||||
|
|
||||||
addInstructionsWithLabels(
|
|
||||||
0,
|
|
||||||
"""
|
|
||||||
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->getTabletLayoutEnabled()Z
|
|
||||||
move-result v0
|
|
||||||
if-nez v0, :is_large_form_factor
|
|
||||||
""",
|
|
||||||
ExternalLabel(
|
|
||||||
"is_large_form_factor",
|
|
||||||
returnIsLargeFormFactorLabel,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.layout.tablet
|
|
||||||
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import app.revanced.patcher.fingerprint
|
|
||||||
|
|
||||||
internal val getFormFactorFingerprint = fingerprint {
|
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
|
||||||
returns("L")
|
|
||||||
parameters("Landroid/content/Context;", "Ljava/util/List;")
|
|
||||||
opcodes(
|
|
||||||
Opcode.SGET_OBJECT,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT,
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
Opcode.SGET_OBJECT,
|
|
||||||
Opcode.RETURN_OBJECT,
|
|
||||||
Opcode.INVOKE_STATIC,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.RETURN_OBJECT,
|
|
||||||
)
|
|
||||||
strings("")
|
|
||||||
}
|
|
@ -105,3 +105,15 @@ internal val pivotBarConstructorFingerprint = fingerprint {
|
|||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||||
strings("com.google.android.apps.youtube.app.endpoint.flags")
|
strings("com.google.android.apps.youtube.app.endpoint.flags")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal val imageEnumConstructorFingerprint = fingerprint {
|
||||||
|
accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)
|
||||||
|
strings("TAB_ACTIVITY_CAIRO")
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val setEnumMapFingerprint = fingerprint {
|
||||||
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||||
|
literal {
|
||||||
|
ytFillBellId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package app.revanced.patches.youtube.misc.navigation
|
package app.revanced.patches.youtube.misc.navigation
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
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.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
||||||
import app.revanced.patcher.patch.PatchException
|
import app.revanced.patcher.patch.PatchException
|
||||||
@ -12,13 +13,16 @@ import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
|||||||
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||||
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
|
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
|
||||||
|
import app.revanced.patches.youtube.misc.playservice.is_19_35_or_greater
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
|
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||||
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
|
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||||
|
|
||||||
@ -26,6 +30,8 @@ internal var imageOnlyTabResourceId = -1L
|
|||||||
private set
|
private set
|
||||||
internal var actionBarSearchResultsViewMicId = -1L
|
internal var actionBarSearchResultsViewMicId = -1L
|
||||||
private set
|
private set
|
||||||
|
internal var ytFillBellId = -1L
|
||||||
|
private set
|
||||||
|
|
||||||
private val navigationBarHookResourcePatch = resourcePatch {
|
private val navigationBarHookResourcePatch = resourcePatch {
|
||||||
dependsOn(resourceMappingPatch)
|
dependsOn(resourceMappingPatch)
|
||||||
@ -33,6 +39,7 @@ private val navigationBarHookResourcePatch = resourcePatch {
|
|||||||
execute {
|
execute {
|
||||||
imageOnlyTabResourceId = resourceMappings["layout", "image_only_tab"]
|
imageOnlyTabResourceId = resourceMappings["layout", "image_only_tab"]
|
||||||
actionBarSearchResultsViewMicId = resourceMappings["layout", "action_bar_search_results_view_mic"]
|
actionBarSearchResultsViewMicId = resourceMappings["layout", "action_bar_search_results_view_mic"]
|
||||||
|
ytFillBellId = resourceMappings["drawable", "yt_fill_bell_black_24"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,6 +151,36 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig
|
|||||||
"(${EXTENSION_NAVIGATION_BUTTON_DESCRIPTOR}Landroid/view/View;)V",
|
"(${EXTENSION_NAVIGATION_BUTTON_DESCRIPTOR}Landroid/view/View;)V",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix YT bug of notification tab missing the filled icon.
|
||||||
|
if (is_19_35_or_greater) {
|
||||||
|
val cairoNotificationEnumReference = with(imageEnumConstructorFingerprint) {
|
||||||
|
val stringIndex = stringMatches!!.first().index
|
||||||
|
val cairoNotificationEnumIndex = method.indexOfFirstInstructionOrThrow(stringIndex) {
|
||||||
|
opcode == Opcode.SPUT_OBJECT
|
||||||
|
}
|
||||||
|
method.getInstruction<ReferenceInstruction>(cairoNotificationEnumIndex).reference
|
||||||
|
}
|
||||||
|
|
||||||
|
setEnumMapFingerprint.method.apply {
|
||||||
|
val enumMapIndex = indexOfFirstInstructionReversedOrThrow {
|
||||||
|
val reference = getReference<MethodReference>()
|
||||||
|
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||||
|
reference?.definingClass == "Ljava/util/EnumMap;" &&
|
||||||
|
reference.name == "put" &&
|
||||||
|
reference.parameterTypes.firstOrNull() == "Ljava/lang/Enum;"
|
||||||
|
}
|
||||||
|
val instruction = getInstruction<FiveRegisterInstruction>(enumMapIndex)
|
||||||
|
|
||||||
|
addInstructions(
|
||||||
|
enumMapIndex + 1,
|
||||||
|
"""
|
||||||
|
sget-object v${instruction.registerD}, $cairoNotificationEnumReference
|
||||||
|
invoke-static { v${instruction.registerC}, v${instruction.registerD} }, $EXTENSION_CLASS_DESCRIPTOR->setCairoNotificationFilledIcon(Ljava/util/EnumMap;Ljava/lang/Enum;)V
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<item>iOS TV</item>
|
<item>iOS TV</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="revanced_spoof_video_streams_client_type_entry_values">
|
<string-array name="revanced_spoof_video_streams_client_type_entry_values">
|
||||||
<!-- Enum names from extension -->
|
<!-- Extension enum names. -->
|
||||||
<item>ANDROID_VR</item>
|
<item>ANDROID_VR</item>
|
||||||
<item>ANDROID_VR_NO_AUTH</item>
|
<item>ANDROID_VR_NO_AUTH</item>
|
||||||
<item>ANDROID_UNPLUGGED</item>
|
<item>ANDROID_UNPLUGGED</item>
|
||||||
@ -148,6 +148,21 @@
|
|||||||
<item>17.33.42</item>
|
<item>17.33.42</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
</patch>
|
</patch>
|
||||||
|
<patch id="layout.formfactor.changeFormFactorPatch">
|
||||||
|
<string-array name="revanced_change_form_factor_entries">
|
||||||
|
<item>@string/revanced_change_form_factor_entry_1</item>
|
||||||
|
<item>@string/revanced_change_form_factor_entry_2</item>
|
||||||
|
<item>@string/revanced_change_form_factor_entry_3</item>
|
||||||
|
<item>@string/revanced_change_form_factor_entry_4</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="revanced_change_form_factor_entry_values">
|
||||||
|
<!-- Extension enum names. -->
|
||||||
|
<item>DEFAULT</item>
|
||||||
|
<item>SMALL</item>
|
||||||
|
<item>LARGE</item>
|
||||||
|
<item>AUTOMOTIVE</item>
|
||||||
|
</string-array>
|
||||||
|
</patch>
|
||||||
<patch id="layout.player.fullscreen.exitFullscreenPatch">
|
<patch id="layout.player.fullscreen.exitFullscreenPatch">
|
||||||
<string-array name="revanced_exit_fullscreen_entries">
|
<string-array name="revanced_exit_fullscreen_entries">
|
||||||
<item>@string/revanced_exit_fullscreen_entry_1</item>
|
<item>@string/revanced_exit_fullscreen_entry_1</item>
|
||||||
@ -174,7 +189,7 @@
|
|||||||
<item>@string/revanced_miniplayer_type_entry_6</item>
|
<item>@string/revanced_miniplayer_type_entry_6</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="revanced_miniplayer_type_entry_values">
|
<string-array name="revanced_miniplayer_type_entry_values">
|
||||||
<!-- Enum names from the extension. -->
|
<!-- Extension enum names. -->
|
||||||
<item>DISABLED</item>
|
<item>DISABLED</item>
|
||||||
<item>DEFAULT</item>
|
<item>DEFAULT</item>
|
||||||
<item>MINIMAL</item>
|
<item>MINIMAL</item>
|
||||||
@ -192,7 +207,7 @@
|
|||||||
<item>@string/revanced_miniplayer_type_entry_6</item>
|
<item>@string/revanced_miniplayer_type_entry_6</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="revanced_miniplayer_type_legacy_entry_values">
|
<string-array name="revanced_miniplayer_type_legacy_entry_values">
|
||||||
<!-- Enum names from the extension. -->
|
<!-- Extension enum names. -->
|
||||||
<item>DEFAULT</item>
|
<item>DEFAULT</item>
|
||||||
<item>MINIMAL</item>
|
<item>MINIMAL</item>
|
||||||
<item>TABLET</item>
|
<item>TABLET</item>
|
||||||
@ -221,7 +236,7 @@
|
|||||||
<item>@string/revanced_change_start_page_entry_browse</item>
|
<item>@string/revanced_change_start_page_entry_browse</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="revanced_change_start_page_entry_values">
|
<string-array name="revanced_change_start_page_entry_values">
|
||||||
<!-- Enum names from extension -->
|
<!-- Extension enum names. -->
|
||||||
<item>DEFAULT</item>
|
<item>DEFAULT</item>
|
||||||
<!-- Intent Action -->
|
<!-- Intent Action -->
|
||||||
<item>SEARCH</item>
|
<item>SEARCH</item>
|
||||||
@ -248,7 +263,7 @@
|
|||||||
<item>@string/revanced_shorts_player_type_regular_player</item>
|
<item>@string/revanced_shorts_player_type_regular_player</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="revanced_shorts_player_type_legacy_entry_values">
|
<string-array name="revanced_shorts_player_type_legacy_entry_values">
|
||||||
<!-- Enum names from extension -->
|
<!-- Extension enum names. -->
|
||||||
<item>SHORTS_PLAYER</item>
|
<item>SHORTS_PLAYER</item>
|
||||||
<item>REGULAR_PLAYER</item>
|
<item>REGULAR_PLAYER</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
@ -272,7 +287,7 @@
|
|||||||
<item>@string/revanced_alt_thumbnail_options_entry_4</item>
|
<item>@string/revanced_alt_thumbnail_options_entry_4</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="revanced_alt_thumbnail_options_entry_values">
|
<string-array name="revanced_alt_thumbnail_options_entry_values">
|
||||||
<!-- Enum names from the extension -->
|
<!-- Extension enum names. -->
|
||||||
<item>ORIGINAL</item>
|
<item>ORIGINAL</item>
|
||||||
<item>DEARROW</item>
|
<item>DEARROW</item>
|
||||||
<item>DEARROW_STILL_IMAGES</item>
|
<item>DEARROW_STILL_IMAGES</item>
|
||||||
|
@ -1029,6 +1029,23 @@ Ready to submit?"</string>
|
|||||||
<string name="revanced_sb_about_api">sponsor.ajay.app</string>
|
<string name="revanced_sb_about_api">sponsor.ajay.app</string>
|
||||||
<string name="revanced_sb_about_api_sum">Data is provided by the SponsorBlock API. Tap here to learn more and see downloads for other platforms</string>
|
<string name="revanced_sb_about_api_sum">Data is provided by the SponsorBlock API. Tap here to learn more and see downloads for other platforms</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
<patch id="layout.formfactor.changeFormFactorPatch">
|
||||||
|
<string name="revanced_change_form_factor_title">Layout form factor</string>
|
||||||
|
<string name="revanced_change_form_factor_entry_1">Default</string>
|
||||||
|
<string name="revanced_change_form_factor_entry_2">Phone</string>
|
||||||
|
<string name="revanced_change_form_factor_entry_3">Tablet</string>
|
||||||
|
<string name="revanced_change_form_factor_entry_4">Automotive</string>
|
||||||
|
<string name="revanced_change_form_factor_user_dialog_message">"Changes include:
|
||||||
|
|
||||||
|
Tablet layout
|
||||||
|
• Community posts are hidden
|
||||||
|
|
||||||
|
Automotive layout
|
||||||
|
• Watch history menu is hidden
|
||||||
|
• Explore tab is restored
|
||||||
|
• Shorts open in the regular player
|
||||||
|
• Feed is organized by topics and channel"</string>
|
||||||
|
</patch>
|
||||||
<patch id="layout.spoofappversion.spoofAppVersionPatch">
|
<patch id="layout.spoofappversion.spoofAppVersionPatch">
|
||||||
<string name="revanced_spoof_app_version_title">Spoof app version</string>
|
<string name="revanced_spoof_app_version_title">Spoof app version</string>
|
||||||
<string name="revanced_spoof_app_version_summary_on">Version spoofed</string>
|
<string name="revanced_spoof_app_version_summary_on">Version spoofed</string>
|
||||||
@ -1086,12 +1103,6 @@ If later turned off, it is recommended to clear the app data to prevent UI bugs.
|
|||||||
<string name="revanced_shorts_autoplay_background_summary_on">Shorts background play will autoplay</string>
|
<string name="revanced_shorts_autoplay_background_summary_on">Shorts background play will autoplay</string>
|
||||||
<string name="revanced_shorts_autoplay_background_summary_off">Shorts background play will repeat</string>
|
<string name="revanced_shorts_autoplay_background_summary_off">Shorts background play will repeat</string>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="layout.tablet.enableTabletLayoutPatch">
|
|
||||||
<string name="revanced_tablet_layout_title">Enable tablet layout</string>
|
|
||||||
<string name="revanced_tablet_layout_summary_on">Tablet layout is enabled</string>
|
|
||||||
<string name="revanced_tablet_layout_summary_off">Tablet layout is disabled</string>
|
|
||||||
<string name="revanced_tablet_layout_user_dialog_message">Community posts do not show up on tablet layouts</string>
|
|
||||||
</patch>x
|
|
||||||
<patch id="layout.miniplayer.miniplayerPatch">
|
<patch id="layout.miniplayer.miniplayerPatch">
|
||||||
<string name="revanced_miniplayer_screen_title">Miniplayer</string>
|
<string name="revanced_miniplayer_screen_title">Miniplayer</string>
|
||||||
<string name="revanced_miniplayer_screen_summary">Change the style of the in app minimized player</string>
|
<string name="revanced_miniplayer_screen_summary">Change the style of the in app minimized player</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user