mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-14 05:14:37 +01:00
Compare commits
12 Commits
v5.3.0-dev
...
v5.3.0-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd400ac2a0 | ||
|
|
538ed6d876 | ||
|
|
5ff94dc34a | ||
|
|
b04a11a885 | ||
|
|
4983e021f9 | ||
|
|
bee917f4ed | ||
|
|
c94376bc4c | ||
|
|
87fe83aacf | ||
|
|
92d282e963 | ||
|
|
4a88f650c2 | ||
|
|
8b67716506 | ||
|
|
95d56b1529 |
41
CHANGELOG.md
41
CHANGELOG.md
@@ -1,3 +1,44 @@
|
|||||||
|
# [5.3.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.3.0-dev.5...v5.3.0-dev.6) (2024-12-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **YouTube - Spoof video streams:** Allow picking a default audio language track ([#4050](https://github.com/ReVanced/revanced-patches/issues/4050)) ([ede666b](https://github.com/ReVanced/revanced-patches/commit/ede666b5cb64fcbaa1334ad8bef79e2634ced113))
|
||||||
|
|
||||||
|
# [5.3.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.3.0-dev.4...v5.3.0-dev.5) (2024-12-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **Change package name:** Prevent applying the patch to known incompatible apps ([#3943](https://github.com/ReVanced/revanced-patches/issues/3943)) ([44936e7](https://github.com/ReVanced/revanced-patches/commit/44936e71e846f72f7279950232a5dba37765ceb3))
|
||||||
|
* **YouTube Music - Permanent shuffle:** Remove obsolete and non functional patch ([#4073](https://github.com/ReVanced/revanced-patches/issues/4073)) ([fbc6ab6](https://github.com/ReVanced/revanced-patches/commit/fbc6ab6a357b351f02d4d486ddc2072cf53199c3))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **YouTube:** Add `Open videos fullscreen` patch ([#4069](https://github.com/ReVanced/revanced-patches/issues/4069)) ([296d63b](https://github.com/ReVanced/revanced-patches/commit/296d63bd42c338a01efbcb2df702e5822d05a5f1))
|
||||||
|
|
||||||
|
# [5.3.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.3.0-dev.3...v5.3.0-dev.4) (2024-12-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Nyx:** Remove broken `Unlock pro` patch ([1fe8b16](https://github.com/ReVanced/revanced-patches/commit/1fe8b164eab0c4fa80ab2da2581977f5111a2858))
|
||||||
|
|
||||||
|
# [5.3.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.3.0-dev.2...v5.3.0-dev.3) (2024-12-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **YouTube - Spoof video streams:** Update `Force AVC` client data ([#4064](https://github.com/ReVanced/revanced-patches/issues/4064)) ([7d537dd](https://github.com/ReVanced/revanced-patches/commit/7d537ddff4bb5421fa320741275131a66ef5c7bb))
|
||||||
|
|
||||||
|
# [5.3.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.3.0-dev.1...v5.3.0-dev.2) (2024-12-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **Reddit:** Fix patches by using correct extension class ([70bdc68](https://github.com/ReVanced/revanced-patches/commit/70bdc6840d465399625aa1ae0259f49e72711955))
|
||||||
|
|
||||||
# [5.3.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.2.4-dev.3...v5.3.0-dev.1) (2024-12-08)
|
# [5.3.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.2.4-dev.3...v5.3.0-dev.1) (2024-12-08)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
package app.revanced.extension.patches;
|
package app.revanced.extension.reddit.patches;
|
||||||
|
|
||||||
import com.reddit.domain.model.ILink;
|
import com.reddit.domain.model.ILink;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
public final class FilterPromotedLinksPatch {
|
public final class FilterPromotedLinksPatch {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Injection point.
|
||||||
|
*
|
||||||
* Filters list from promoted links.
|
* Filters list from promoted links.
|
||||||
**/
|
**/
|
||||||
public static List<?> filterChildren(final Iterable<?> links) {
|
public static List<?> filterChildren(final Iterable<?> links) {
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
package app.revanced.extension.shared.settings;
|
package app.revanced.extension.shared.settings;
|
||||||
|
|
||||||
import app.revanced.extension.shared.spoof.ClientType;
|
|
||||||
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
|
|
||||||
|
|
||||||
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.parent;
|
import static app.revanced.extension.shared.settings.Setting.parent;
|
||||||
|
import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.ForceiOSAVCAvailability;
|
||||||
|
|
||||||
|
import app.revanced.extension.shared.spoof.AudioStreamLanguage;
|
||||||
|
import app.revanced.extension.shared.spoof.ClientType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Settings shared across multiple apps.
|
* Settings shared across multiple apps.
|
||||||
@@ -21,8 +22,9 @@ public class BaseSettings {
|
|||||||
public static final IntegerSetting CHECK_ENVIRONMENT_WARNINGS_ISSUED = new IntegerSetting("revanced_check_environment_warnings_issued", 0, true, false);
|
public static final IntegerSetting CHECK_ENVIRONMENT_WARNINGS_ISSUED = new IntegerSetting("revanced_check_environment_warnings_issued", 0, true, false);
|
||||||
|
|
||||||
public static final BooleanSetting SPOOF_VIDEO_STREAMS = new BooleanSetting("revanced_spoof_video_streams", TRUE, true, "revanced_spoof_video_streams_user_dialog_message");
|
public static final BooleanSetting SPOOF_VIDEO_STREAMS = new BooleanSetting("revanced_spoof_video_streams", TRUE, true, "revanced_spoof_video_streams_user_dialog_message");
|
||||||
|
public static final EnumSetting<AudioStreamLanguage> SPOOF_VIDEO_STREAMS_LANGUAGE = new EnumSetting<>("revanced_spoof_video_streams_language", AudioStreamLanguage.DEFAULT);
|
||||||
public static final BooleanSetting SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC = new BooleanSetting("revanced_spoof_video_streams_ios_force_avc", FALSE, true,
|
public static final BooleanSetting SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC = new BooleanSetting("revanced_spoof_video_streams_ios_force_avc", FALSE, true,
|
||||||
"revanced_spoof_video_streams_ios_force_avc_user_dialog_message", new SpoofVideoStreamsPatch.ForceiOSAVCAvailability());
|
"revanced_spoof_video_streams_ios_force_avc_user_dialog_message", new ForceiOSAVCAvailability());
|
||||||
public static final EnumSetting<ClientType> SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client", ClientType.ANDROID_VR, true, parent(SPOOF_VIDEO_STREAMS));
|
public static final EnumSetting<ClientType> SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client", ClientType.ANDROID_VR, true, parent(SPOOF_VIDEO_STREAMS));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,102 @@
|
|||||||
|
package app.revanced.extension.shared.spoof;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public enum AudioStreamLanguage {
|
||||||
|
DEFAULT,
|
||||||
|
|
||||||
|
// Language codes found in locale_config.xml
|
||||||
|
// Region specific variants of Chinese/English/Spanish/French have been removed.
|
||||||
|
AF,
|
||||||
|
AM,
|
||||||
|
AR,
|
||||||
|
AS,
|
||||||
|
AZ,
|
||||||
|
BE,
|
||||||
|
BG,
|
||||||
|
BN,
|
||||||
|
BS,
|
||||||
|
CA,
|
||||||
|
CS,
|
||||||
|
DA,
|
||||||
|
DE,
|
||||||
|
EL,
|
||||||
|
EN,
|
||||||
|
ES,
|
||||||
|
ET,
|
||||||
|
EU,
|
||||||
|
FA,
|
||||||
|
FI,
|
||||||
|
FR,
|
||||||
|
GL,
|
||||||
|
GU,
|
||||||
|
HI,
|
||||||
|
HE, // App uses obsolete 'IW' and 'HE' is modern ISO code.
|
||||||
|
HR,
|
||||||
|
HU,
|
||||||
|
HY,
|
||||||
|
ID,
|
||||||
|
IS,
|
||||||
|
IT,
|
||||||
|
JA,
|
||||||
|
KA,
|
||||||
|
KK,
|
||||||
|
KM,
|
||||||
|
KN,
|
||||||
|
KO,
|
||||||
|
KY,
|
||||||
|
LO,
|
||||||
|
LT,
|
||||||
|
LV,
|
||||||
|
MK,
|
||||||
|
ML,
|
||||||
|
MN,
|
||||||
|
MR,
|
||||||
|
MS,
|
||||||
|
MY,
|
||||||
|
NE,
|
||||||
|
NL,
|
||||||
|
NB,
|
||||||
|
OR,
|
||||||
|
PA,
|
||||||
|
PL,
|
||||||
|
PT_BR,
|
||||||
|
PT_PT,
|
||||||
|
RO,
|
||||||
|
RU,
|
||||||
|
SI,
|
||||||
|
SK,
|
||||||
|
SL,
|
||||||
|
SQ,
|
||||||
|
SR,
|
||||||
|
SV,
|
||||||
|
SW,
|
||||||
|
TA,
|
||||||
|
TE,
|
||||||
|
TH,
|
||||||
|
TL,
|
||||||
|
TR,
|
||||||
|
UK,
|
||||||
|
UR,
|
||||||
|
UZ,
|
||||||
|
VI,
|
||||||
|
ZH,
|
||||||
|
ZU;
|
||||||
|
|
||||||
|
private final String iso639_1;
|
||||||
|
|
||||||
|
AudioStreamLanguage() {
|
||||||
|
iso639_1 = name().replace('_', '-');
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIso639_1() {
|
||||||
|
// Changing the app language does not force the app to completely restart,
|
||||||
|
// so the default needs to be the current language and not a static field.
|
||||||
|
if (this == DEFAULT) {
|
||||||
|
// Android VR requires uppercase language code.
|
||||||
|
return Locale.getDefault().toLanguageTag().toUpperCase(Locale.US);
|
||||||
|
}
|
||||||
|
|
||||||
|
return iso639_1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
package app.revanced.extension.shared.spoof;
|
package app.revanced.extension.shared.spoof;
|
||||||
|
|
||||||
import static app.revanced.extension.shared.spoof.DeviceHardwareSupport.allowAV1;
|
|
||||||
import static app.revanced.extension.shared.spoof.DeviceHardwareSupport.allowVP9;
|
|
||||||
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import app.revanced.extension.shared.settings.BaseSettings;
|
||||||
|
|
||||||
public enum ClientType {
|
public enum ClientType {
|
||||||
// Specific purpose for age restricted, or private videos, because the iOS client is not logged in.
|
// Specific purpose for age restricted, or private videos, because the iOS client is not logged in.
|
||||||
// https://dumps.tadiphone.dev/dumps/oculus/eureka
|
// https://dumps.tadiphone.dev/dumps/oculus/eureka
|
||||||
@@ -16,31 +15,35 @@ public enum ClientType {
|
|||||||
"com.google.android.apps.youtube.vr.oculus/1.56.21 (Linux; U; Android 12; GB) gzip",
|
"com.google.android.apps.youtube.vr.oculus/1.56.21 (Linux; U; Android 12; GB) gzip",
|
||||||
"32", // Android 12.1
|
"32", // Android 12.1
|
||||||
"1.56.21",
|
"1.56.21",
|
||||||
"ANDROID_VR",
|
|
||||||
true
|
true
|
||||||
),
|
),
|
||||||
// Specific for kids videos.
|
// Specific for kids videos.
|
||||||
IOS(5,
|
IOS(5,
|
||||||
// iPhone 15 supports AV1 hardware decoding.
|
forceAVC()
|
||||||
// Only use if this Android device also has hardware decoding.
|
? "iPhone12,5" // 11 Pro Max (last device with iOS 13)
|
||||||
allowAV1()
|
: "iPhone16,2", // 15 Pro Max
|
||||||
? "iPhone16,2" // 15 Pro Max
|
// iOS 13 and earlier uses only AVC. 14+ adds VP9 and AV1.
|
||||||
: "iPhone11,4", // XS Max
|
forceAVC()
|
||||||
// iOS 14+ forces VP9.
|
? "13.7.17H35" // Last release of iOS 13.
|
||||||
allowVP9()
|
: "17.5.1.21F90",
|
||||||
? "17.5.1.21F90"
|
forceAVC()
|
||||||
: "13.7.17H35",
|
? "com.google.ios.youtube/17.40.5 (iPhone; U; CPU iOS 13_7 like Mac OS X)"
|
||||||
allowVP9()
|
: "com.google.ios.youtube/19.47.7 (iPhone; U; CPU iOS 17_5_1 like Mac OS X)",
|
||||||
? "com.google.ios.youtube/19.47.7 (iPhone; U; CPU iOS 17_5_1 like Mac OS X)"
|
|
||||||
: "com.google.ios.youtube/19.47.7 (iPhone; U; CPU iOS 13_7 like Mac OS X)",
|
|
||||||
null,
|
null,
|
||||||
// Version number should be a valid iOS release.
|
// Version number should be a valid iOS release.
|
||||||
// https://www.ipa4fun.com/history/185230
|
// https://www.ipa4fun.com/history/185230
|
||||||
"19.47.7",
|
forceAVC()
|
||||||
"IOS",
|
// Some newer versions can also force AVC,
|
||||||
|
// but 17.40 is the last version that supports iOS 13.
|
||||||
|
? "17.40.5"
|
||||||
|
: "19.47.7",
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
private static boolean forceAVC() {
|
||||||
|
return BaseSettings.SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC.get();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* YouTube
|
* YouTube
|
||||||
* <a href="https://github.com/zerodytrash/YouTube-Internal-Clients?tab=readme-ov-file#clients">client type</a>
|
* <a href="https://github.com/zerodytrash/YouTube-Internal-Clients?tab=readme-ov-file#clients">client type</a>
|
||||||
@@ -69,11 +72,6 @@ public enum ClientType {
|
|||||||
@Nullable
|
@Nullable
|
||||||
public final String androidSdkVersion;
|
public final String androidSdkVersion;
|
||||||
|
|
||||||
/**
|
|
||||||
* Client name.
|
|
||||||
*/
|
|
||||||
public final String clientName;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* App version.
|
* App version.
|
||||||
*/
|
*/
|
||||||
@@ -90,7 +88,6 @@ public enum ClientType {
|
|||||||
String userAgent,
|
String userAgent,
|
||||||
@Nullable String androidSdkVersion,
|
@Nullable String androidSdkVersion,
|
||||||
String clientVersion,
|
String clientVersion,
|
||||||
String clientName,
|
|
||||||
boolean canLogin
|
boolean canLogin
|
||||||
) {
|
) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
@@ -99,7 +96,6 @@ public enum ClientType {
|
|||||||
this.userAgent = userAgent;
|
this.userAgent = userAgent;
|
||||||
this.androidSdkVersion = androidSdkVersion;
|
this.androidSdkVersion = androidSdkVersion;
|
||||||
this.clientVersion = clientVersion;
|
this.clientVersion = clientVersion;
|
||||||
this.clientName = clientName;
|
|
||||||
this.canLogin = canLogin;
|
this.canLogin = canLogin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
package app.revanced.extension.shared.spoof;
|
|
||||||
|
|
||||||
import android.media.MediaCodecInfo;
|
|
||||||
import android.media.MediaCodecList;
|
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
import app.revanced.extension.shared.Logger;
|
|
||||||
import app.revanced.extension.shared.settings.BaseSettings;
|
|
||||||
|
|
||||||
public class DeviceHardwareSupport {
|
|
||||||
public static final boolean DEVICE_HAS_HARDWARE_DECODING_VP9;
|
|
||||||
public static final boolean DEVICE_HAS_HARDWARE_DECODING_AV1;
|
|
||||||
|
|
||||||
static {
|
|
||||||
boolean vp9found = false;
|
|
||||||
boolean av1found = false;
|
|
||||||
MediaCodecList codecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
|
|
||||||
final boolean deviceIsAndroidTenOrLater = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
|
|
||||||
|
|
||||||
for (MediaCodecInfo codecInfo : codecList.getCodecInfos()) {
|
|
||||||
final boolean isHardwareAccelerated = deviceIsAndroidTenOrLater
|
|
||||||
? codecInfo.isHardwareAccelerated()
|
|
||||||
: !codecInfo.getName().startsWith("OMX.google"); // Software decoder.
|
|
||||||
if (isHardwareAccelerated && !codecInfo.isEncoder()) {
|
|
||||||
for (String type : codecInfo.getSupportedTypes()) {
|
|
||||||
if (type.equalsIgnoreCase("video/x-vnd.on2.vp9")) {
|
|
||||||
vp9found = true;
|
|
||||||
} else if (type.equalsIgnoreCase("video/av01")) {
|
|
||||||
av1found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEVICE_HAS_HARDWARE_DECODING_VP9 = vp9found;
|
|
||||||
DEVICE_HAS_HARDWARE_DECODING_AV1 = av1found;
|
|
||||||
|
|
||||||
Logger.printDebug(() -> DEVICE_HAS_HARDWARE_DECODING_AV1
|
|
||||||
? "Device supports AV1 hardware decoding\n"
|
|
||||||
: "Device does not support AV1 hardware decoding\n"
|
|
||||||
+ (DEVICE_HAS_HARDWARE_DECODING_VP9
|
|
||||||
? "Device supports VP9 hardware decoding"
|
|
||||||
: "Device does not support VP9 hardware decoding"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean allowVP9() {
|
|
||||||
return DEVICE_HAS_HARDWARE_DECODING_VP9 && !BaseSettings.SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean allowAV1() {
|
|
||||||
return allowVP9() && DEVICE_HAS_HARDWARE_DECODING_AV1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -13,7 +13,6 @@ import app.revanced.extension.shared.Utils;
|
|||||||
import app.revanced.extension.shared.settings.BaseSettings;
|
import app.revanced.extension.shared.settings.BaseSettings;
|
||||||
import app.revanced.extension.shared.settings.Setting;
|
import app.revanced.extension.shared.settings.Setting;
|
||||||
import app.revanced.extension.shared.spoof.requests.StreamingDataRequest;
|
import app.revanced.extension.shared.spoof.requests.StreamingDataRequest;
|
||||||
import app.revanced.extension.shared.settings.BaseSettings;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class SpoofVideoStreamsPatch {
|
public class SpoofVideoStreamsPatch {
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ import java.io.IOException;
|
|||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
|
|
||||||
import app.revanced.extension.shared.Logger;
|
import app.revanced.extension.shared.Logger;
|
||||||
import app.revanced.extension.shared.Utils;
|
|
||||||
import app.revanced.extension.shared.requests.Requester;
|
import app.revanced.extension.shared.requests.Requester;
|
||||||
import app.revanced.extension.shared.requests.Route;
|
import app.revanced.extension.shared.requests.Route;
|
||||||
|
import app.revanced.extension.shared.settings.BaseSettings;
|
||||||
import app.revanced.extension.shared.spoof.ClientType;
|
import app.revanced.extension.shared.spoof.ClientType;
|
||||||
|
|
||||||
final class PlayerRoutes {
|
final class PlayerRoutes {
|
||||||
@@ -25,9 +25,6 @@ final class PlayerRoutes {
|
|||||||
*/
|
*/
|
||||||
private static final int CONNECTION_TIMEOUT_MILLISECONDS = 10 * 1000; // 10 Seconds.
|
private static final int CONNECTION_TIMEOUT_MILLISECONDS = 10 * 1000; // 10 Seconds.
|
||||||
|
|
||||||
private static final String LOCALE_LANGUAGE = Utils.getContext().getResources()
|
|
||||||
.getConfiguration().locale.getLanguage();
|
|
||||||
|
|
||||||
private PlayerRoutes() {
|
private PlayerRoutes() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,8 +35,7 @@ final class PlayerRoutes {
|
|||||||
JSONObject context = new JSONObject();
|
JSONObject context = new JSONObject();
|
||||||
|
|
||||||
JSONObject client = new JSONObject();
|
JSONObject client = new JSONObject();
|
||||||
// Required to use correct default audio channel with iOS.
|
client.put("hl", BaseSettings.SPOOF_VIDEO_STREAMS_LANGUAGE.get().getIso639_1());
|
||||||
client.put("hl", LOCALE_LANGUAGE);
|
|
||||||
client.put("clientName", clientType.name());
|
client.put("clientName", clientType.name());
|
||||||
client.put("clientVersion", clientType.clientVersion);
|
client.put("clientVersion", clientType.clientVersion);
|
||||||
client.put("deviceModel", clientType.deviceModel);
|
client.put("deviceModel", clientType.deviceModel);
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package app.revanced.extension.youtube.patches;
|
||||||
|
|
||||||
|
import app.revanced.extension.youtube.settings.Settings;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class OpenVideosFullscreen {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point.
|
||||||
|
*/
|
||||||
|
public static boolean openVideoFullscreenPortrait(boolean original) {
|
||||||
|
return Settings.OPEN_VIDEOS_FULLSCREEN_PORTRAIT.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -55,7 +55,7 @@ public class ThemePatch {
|
|||||||
/**
|
/**
|
||||||
* Injection point.
|
* Injection point.
|
||||||
*/
|
*/
|
||||||
public static boolean gradientLoadingScreenEnabled() {
|
public static boolean gradientLoadingScreenEnabled(boolean original) {
|
||||||
return GRADIENT_LOADING_SCREEN_ENABLED;
|
return GRADIENT_LOADING_SCREEN_ENABLED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ public class Settings extends BaseSettings {
|
|||||||
public static final BooleanSetting PLAYBACK_SPEED_DIALOG_BUTTON = new BooleanSetting("revanced_playback_speed_dialog_button", FALSE);
|
public static final BooleanSetting PLAYBACK_SPEED_DIALOG_BUTTON = new BooleanSetting("revanced_playback_speed_dialog_button", FALSE);
|
||||||
public static final BooleanSetting PLAYER_POPUP_PANELS = new BooleanSetting("revanced_hide_player_popup_panels", FALSE);
|
public static final BooleanSetting PLAYER_POPUP_PANELS = new BooleanSetting("revanced_hide_player_popup_panels", FALSE);
|
||||||
public static final IntegerSetting PLAYER_OVERLAY_OPACITY = new IntegerSetting("revanced_player_overlay_opacity", 100, true);
|
public static final IntegerSetting PLAYER_OVERLAY_OPACITY = new IntegerSetting("revanced_player_overlay_opacity", 100, true);
|
||||||
|
public static final BooleanSetting OPEN_VIDEOS_FULLSCREEN_PORTRAIT = new BooleanSetting("revanced_open_videos_fullscreen_portrait", FALSE);
|
||||||
// Miniplayer
|
// Miniplayer
|
||||||
public static final EnumSetting<MiniplayerType> MINIPLAYER_TYPE = new EnumSetting<>("revanced_miniplayer_type", MiniplayerType.ORIGINAL, true);
|
public static final EnumSetting<MiniplayerType> MINIPLAYER_TYPE = new EnumSetting<>("revanced_miniplayer_type", MiniplayerType.ORIGINAL, true);
|
||||||
private static final Availability MINIPLAYER_ANY_MODERN = MINIPLAYER_TYPE.availability(MODERN_1, MODERN_2, MODERN_3, MODERN_4);
|
private static final Availability MINIPLAYER_ANY_MODERN = MINIPLAYER_TYPE.availability(MODERN_1, MODERN_2, MODERN_3, MODERN_4);
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
package app.revanced.extension.youtube.settings.preference;
|
|
||||||
|
|
||||||
import static app.revanced.extension.shared.StringRef.str;
|
|
||||||
import static app.revanced.extension.shared.spoof.DeviceHardwareSupport.DEVICE_HAS_HARDWARE_DECODING_VP9;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.preference.SwitchPreference;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
|
|
||||||
@SuppressWarnings({"unused", "deprecation"})
|
|
||||||
public class ForceAVCSpoofingPreference extends SwitchPreference {
|
|
||||||
{
|
|
||||||
if (!DEVICE_HAS_HARDWARE_DECODING_VP9) {
|
|
||||||
setSummaryOn(str("revanced_spoof_video_streams_ios_force_avc_no_hardware_vp9_summary_on"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ForceAVCSpoofingPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
|
||||||
super(context, attrs, defStyleAttr, defStyleRes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ForceAVCSpoofingPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
||||||
super(context, attrs, defStyleAttr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ForceAVCSpoofingPreference(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ForceAVCSpoofingPreference(Context context) {
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateUI() {
|
|
||||||
if (DEVICE_HAS_HARDWARE_DECODING_VP9) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Temporarily remove the preference key to allow changing this preference without
|
|
||||||
// causing the settings UI listeners from showing reboot dialogs by the changes made here.
|
|
||||||
String key = getKey();
|
|
||||||
setKey(null);
|
|
||||||
|
|
||||||
// This setting cannot be changed by the user.
|
|
||||||
super.setEnabled(false);
|
|
||||||
super.setChecked(true);
|
|
||||||
|
|
||||||
setKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setEnabled(boolean enabled) {
|
|
||||||
super.setEnabled(enabled);
|
|
||||||
|
|
||||||
updateUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setChecked(boolean checked) {
|
|
||||||
super.setChecked(checked);
|
|
||||||
|
|
||||||
updateUI();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,6 +10,7 @@ import android.os.Build;
|
|||||||
import android.preference.ListPreference;
|
import android.preference.ListPreference;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceScreen;
|
import android.preference.PreferenceScreen;
|
||||||
|
import android.util.Pair;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.WindowInsets;
|
import android.view.WindowInsets;
|
||||||
@@ -18,6 +19,10 @@ import android.widget.Toolbar;
|
|||||||
|
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
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.shared.settings.preference.AbstractPreferenceFragment;
|
import app.revanced.extension.shared.settings.preference.AbstractPreferenceFragment;
|
||||||
@@ -41,6 +46,46 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
|||||||
return Utils.getContext().getResources().getDrawable(backButtonResource);
|
return Utils.getContext().getResources().getDrawable(backButtonResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorts a preference list by menu entries, but preserves the first value as the first entry.
|
||||||
|
*/
|
||||||
|
private static void sortListPreferenceByValues(ListPreference listPreference) {
|
||||||
|
CharSequence[] entries = listPreference.getEntries();
|
||||||
|
CharSequence[] entryValues = listPreference.getEntryValues();
|
||||||
|
final int entrySize = entries.length;
|
||||||
|
|
||||||
|
if (entrySize != entryValues.length) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the first entry remains the first after sorting.
|
||||||
|
CharSequence firstEntry = entries[0];
|
||||||
|
CharSequence firstEntryValue = entryValues[0];
|
||||||
|
|
||||||
|
List<Pair<String, String>> entryPairs = new ArrayList<>(entrySize);
|
||||||
|
for (int i = 1; i < entrySize; i++) {
|
||||||
|
entryPairs.add(new Pair<>(entries[i].toString(), entryValues[i].toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.sort(entryPairs, (pair1, pair2) -> pair1.first.compareToIgnoreCase(pair2.first));
|
||||||
|
|
||||||
|
CharSequence[] sortedEntries = new CharSequence[entrySize];
|
||||||
|
CharSequence[] sortedEntryValues = new CharSequence[entrySize];
|
||||||
|
|
||||||
|
sortedEntries[0] = firstEntry;
|
||||||
|
sortedEntryValues[0] = firstEntryValue;
|
||||||
|
|
||||||
|
int i = 1;
|
||||||
|
for (Pair<String, String> pair : entryPairs) {
|
||||||
|
sortedEntries[i] = pair.first;
|
||||||
|
sortedEntryValues[i] = pair.second;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
listPreference.setEntries(sortedEntries);
|
||||||
|
listPreference.setEntryValues(sortedEntryValues);
|
||||||
|
}
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
@Override
|
@Override
|
||||||
protected void initialize() {
|
protected void initialize() {
|
||||||
@@ -50,9 +95,14 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
|||||||
setPreferenceScreenToolbar(getPreferenceScreen());
|
setPreferenceScreenToolbar(getPreferenceScreen());
|
||||||
|
|
||||||
// If the preference was included, then initialize it based on the available playback speed.
|
// If the preference was included, then initialize it based on the available playback speed.
|
||||||
Preference defaultSpeedPreference = findPreference(Settings.PLAYBACK_SPEED_DEFAULT.key);
|
Preference preference = findPreference(Settings.PLAYBACK_SPEED_DEFAULT.key);
|
||||||
if (defaultSpeedPreference instanceof ListPreference) {
|
if (preference instanceof ListPreference playbackPreference) {
|
||||||
CustomPlaybackSpeedPatch.initializeListPreference((ListPreference) defaultSpeedPreference);
|
CustomPlaybackSpeedPatch.initializeListPreference(playbackPreference);
|
||||||
|
}
|
||||||
|
|
||||||
|
preference = findPreference(Settings.SPOOF_VIDEO_STREAMS_LANGUAGE.key);
|
||||||
|
if (preference instanceof ListPreference languagePreference) {
|
||||||
|
sortListPreferenceByValues(languagePreference);
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.printException(() -> "initialize failure", ex);
|
Logger.printException(() -> "initialize failure", ex);
|
||||||
|
|||||||
@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
|
|||||||
org.gradle.parallel = true
|
org.gradle.parallel = true
|
||||||
android.useAndroidX = true
|
android.useAndroidX = true
|
||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
version = 5.3.0-dev.1
|
version = 5.3.0-dev.6
|
||||||
|
|||||||
@@ -1164,6 +1164,10 @@ public final class app/revanced/patches/youtube/layout/player/background/PlayerC
|
|||||||
public static final fun getPlayerControlsBackgroundPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
public static final fun getPlayerControlsBackgroundPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenKt {
|
||||||
|
public static final fun getOpenVideosFullscreenPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/youtube/layout/player/overlay/CustomPlayerOverlayOpacityPatchKt {
|
public final class app/revanced/patches/youtube/layout/player/overlay/CustomPlayerOverlayOpacityPatchKt {
|
||||||
public static final fun getCustomPlayerOverlayOpacityPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getCustomPlayerOverlayOpacityPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import app.revanced.patcher.patch.Option
|
|||||||
import app.revanced.patcher.patch.resourcePatch
|
import app.revanced.patcher.patch.resourcePatch
|
||||||
import app.revanced.patcher.patch.stringOption
|
import app.revanced.patcher.patch.stringOption
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
|
import java.util.logging.Logger
|
||||||
|
|
||||||
lateinit var packageNameOption: Option<String>
|
lateinit var packageNameOption: Option<String>
|
||||||
|
|
||||||
@@ -41,18 +42,38 @@ val changePackageNamePatch = resourcePatch(
|
|||||||
it == "Default" || it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$"))
|
it == "Default" || it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apps that are confirmed to not work correctly with this patch.
|
||||||
|
* This is not an exhaustive list, and is only the apps with
|
||||||
|
* ReVanced specific patches and are confirmed incompatible with this patch.
|
||||||
|
*/
|
||||||
|
val incompatibleAppPackages = setOf(
|
||||||
|
// Cannot login, settings menu is broken.
|
||||||
|
"com.reddit.frontpage",
|
||||||
|
|
||||||
|
// Patches and installs but crashes on launch.
|
||||||
|
"com.duolingo",
|
||||||
|
"com.twitter.android",
|
||||||
|
"tv.twitch.android.app",
|
||||||
|
)
|
||||||
|
|
||||||
finalize {
|
finalize {
|
||||||
document("AndroidManifest.xml").use { document ->
|
document("AndroidManifest.xml").use { document ->
|
||||||
|
val manifest = document.getElementsByTagName("manifest").item(0) as Element
|
||||||
|
val originalPackageName = manifest.getAttribute("package")
|
||||||
|
|
||||||
|
if (incompatibleAppPackages.contains(originalPackageName)) {
|
||||||
|
return@finalize Logger.getLogger(this::class.java.name).severe(
|
||||||
|
"'$originalPackageName' does not work correctly with \"Change package name\"")
|
||||||
|
}
|
||||||
|
|
||||||
val replacementPackageName = packageNameOption.value
|
val replacementPackageName = packageNameOption.value
|
||||||
|
|
||||||
val manifest = document.getElementsByTagName("manifest").item(0) as Element
|
|
||||||
manifest.setAttribute(
|
manifest.setAttribute(
|
||||||
"package",
|
"package",
|
||||||
if (replacementPackageName != packageNameOption.default) {
|
if (replacementPackageName != packageNameOption.default) {
|
||||||
replacementPackageName
|
replacementPackageName
|
||||||
} else {
|
} else {
|
||||||
"${manifest.getAttribute("package")}.revanced"
|
"${originalPackageName}.revanced"
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package app.revanced.patches.music.interaction.permanentshuffle
|
|||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
|
||||||
|
@Deprecated("This patch no longer works and will be removed in the future.")
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
val permanentShufflePatch = bytecodePatch(
|
val permanentShufflePatch = bytecodePatch(
|
||||||
name = "Permanent shuffle",
|
|
||||||
description = "Permanently remember your shuffle preference " +
|
description = "Permanently remember your shuffle preference " +
|
||||||
"even if the playlist ends or another track is played.",
|
"even if the playlist ends or another track is played.",
|
||||||
use = false,
|
use = false,
|
||||||
|
|||||||
@@ -3,10 +3,9 @@ package app.revanced.patches.nyx.misc.pro
|
|||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
|
||||||
|
@Deprecated("This patch will be removed in the future.")
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
val unlockProPatch = bytecodePatch(
|
val unlockProPatch = bytecodePatch {
|
||||||
name = "Unlock pro",
|
|
||||||
) {
|
|
||||||
compatibleWith("com.awedea.nyx")
|
compatibleWith("com.awedea.nyx")
|
||||||
|
|
||||||
execute {
|
execute {
|
||||||
|
|||||||
@@ -240,14 +240,14 @@ val miniplayerPatch = bytecodePatch(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
fun MutableMethod.insertBooleanOverride(index: Int, methodName: String) {
|
fun MutableMethod.insertMiniplayerBooleanOverride(index: Int, methodName: String) {
|
||||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||||
addInstructions(
|
addInstructions(
|
||||||
index,
|
index,
|
||||||
"""
|
"""
|
||||||
invoke-static {v$register}, $EXTENSION_CLASS_DESCRIPTOR->$methodName(Z)Z
|
invoke-static {v$register}, $EXTENSION_CLASS_DESCRIPTOR->$methodName(Z)Z
|
||||||
move-result v$register
|
move-result v$register
|
||||||
""",
|
"""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,29 +257,25 @@ val miniplayerPatch = bytecodePatch(
|
|||||||
* Adds an override to force legacy tablet miniplayer to be used or not used.
|
* Adds an override to force legacy tablet miniplayer to be used or not used.
|
||||||
*/
|
*/
|
||||||
fun MutableMethod.insertLegacyTabletMiniplayerOverride(index: Int) {
|
fun MutableMethod.insertLegacyTabletMiniplayerOverride(index: Int) {
|
||||||
insertBooleanOverride(index, "getLegacyTabletMiniplayerOverride")
|
insertMiniplayerBooleanOverride(index, "getLegacyTabletMiniplayerOverride")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an override to force modern miniplayer to be used or not used.
|
* Adds an override to force modern miniplayer to be used or not used.
|
||||||
*/
|
*/
|
||||||
fun MutableMethod.insertModernMiniplayerOverride(index: Int) {
|
fun MutableMethod.insertModernMiniplayerOverride(index: Int) {
|
||||||
insertBooleanOverride(index, "getModernMiniplayerOverride")
|
insertMiniplayerBooleanOverride(index, "getModernMiniplayerOverride")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Fingerprint.insertLiteralValueBooleanOverride(
|
fun Fingerprint.insertMiniplayerFeatureFlagBooleanOverride(
|
||||||
literal: Long,
|
literal: Long,
|
||||||
extensionMethod: String,
|
extensionMethod: String,
|
||||||
) {
|
) = method.insertFeatureFlagBooleanOverride(
|
||||||
method.apply {
|
literal,
|
||||||
val literalIndex = indexOfFirstLiteralInstructionOrThrow(literal)
|
"$EXTENSION_CLASS_DESCRIPTOR->$extensionMethod(Z)Z"
|
||||||
val targetIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT)
|
)
|
||||||
|
|
||||||
insertBooleanOverride(targetIndex + 1, extensionMethod)
|
fun Fingerprint.insertMiniplayerFeatureFlagFloatOverride(
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Fingerprint.insertLiteralValueFloatOverride(
|
|
||||||
literal: Long,
|
literal: Long,
|
||||||
extensionMethod: String,
|
extensionMethod: String,
|
||||||
) {
|
) {
|
||||||
@@ -370,24 +366,24 @@ val miniplayerPatch = bytecodePatch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_19_23_or_greater) {
|
if (is_19_23_or_greater) {
|
||||||
miniplayerModernConstructorFingerprint.insertLiteralValueBooleanOverride(
|
miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride(
|
||||||
MINIPLAYER_DRAG_DROP_FEATURE_KEY,
|
MINIPLAYER_DRAG_DROP_FEATURE_KEY,
|
||||||
"enableMiniplayerDragAndDrop",
|
"enableMiniplayerDragAndDrop",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_19_25_or_greater) {
|
if (is_19_25_or_greater) {
|
||||||
miniplayerModernConstructorFingerprint.insertLiteralValueBooleanOverride(
|
miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride(
|
||||||
MINIPLAYER_MODERN_FEATURE_LEGACY_KEY,
|
MINIPLAYER_MODERN_FEATURE_LEGACY_KEY,
|
||||||
"getModernMiniplayerOverride",
|
"getModernMiniplayerOverride",
|
||||||
)
|
)
|
||||||
|
|
||||||
miniplayerModernConstructorFingerprint.insertLiteralValueBooleanOverride(
|
miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride(
|
||||||
MINIPLAYER_MODERN_FEATURE_KEY,
|
MINIPLAYER_MODERN_FEATURE_KEY,
|
||||||
"getModernFeatureFlagsActiveOverride",
|
"getModernFeatureFlagsActiveOverride",
|
||||||
)
|
)
|
||||||
|
|
||||||
miniplayerModernConstructorFingerprint.insertLiteralValueBooleanOverride(
|
miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride(
|
||||||
MINIPLAYER_DOUBLE_TAP_FEATURE_KEY,
|
MINIPLAYER_DOUBLE_TAP_FEATURE_KEY,
|
||||||
"enableMiniplayerDoubleTapAction",
|
"enableMiniplayerDoubleTapAction",
|
||||||
)
|
)
|
||||||
@@ -426,19 +422,19 @@ val miniplayerPatch = bytecodePatch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_19_36_or_greater) {
|
if (is_19_36_or_greater) {
|
||||||
miniplayerModernConstructorFingerprint.insertLiteralValueBooleanOverride(
|
miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride(
|
||||||
MINIPLAYER_ROUNDED_CORNERS_FEATURE_KEY,
|
MINIPLAYER_ROUNDED_CORNERS_FEATURE_KEY,
|
||||||
"setRoundedCorners",
|
"setRoundedCorners",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_19_43_or_greater) {
|
if (is_19_43_or_greater) {
|
||||||
miniplayerOnCloseHandlerFingerprint.insertLiteralValueBooleanOverride(
|
miniplayerOnCloseHandlerFingerprint.insertMiniplayerFeatureFlagBooleanOverride(
|
||||||
MINIPLAYER_DISABLED_FEATURE_KEY,
|
MINIPLAYER_DISABLED_FEATURE_KEY,
|
||||||
"getMiniplayerOnCloseHandler"
|
"getMiniplayerOnCloseHandler"
|
||||||
)
|
)
|
||||||
|
|
||||||
miniplayerModernConstructorFingerprint.insertLiteralValueBooleanOverride(
|
miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride(
|
||||||
MINIPLAYER_HORIZONTAL_DRAG_FEATURE_KEY,
|
MINIPLAYER_HORIZONTAL_DRAG_FEATURE_KEY,
|
||||||
"setHorizontalDrag",
|
"setHorizontalDrag",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.player.fullscreen
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
import app.revanced.util.literal
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
internal const val OPEN_VIDEOS_FULLSCREEN_PORTRAIT_FEATURE_FLAG = 45666112L
|
||||||
|
|
||||||
|
internal val openVideosFullscreenPortraitFingerprint = fingerprint {
|
||||||
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
|
returns("V")
|
||||||
|
parameters("L", "Lj\$/util/Optional;")
|
||||||
|
literal {
|
||||||
|
OPEN_VIDEOS_FULLSCREEN_PORTRAIT_FEATURE_FLAG
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.player.fullscreen
|
||||||
|
|
||||||
|
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.SwitchPreference
|
||||||
|
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||||
|
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||||
|
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||||
|
import app.revanced.util.insertFeatureFlagBooleanOverride
|
||||||
|
|
||||||
|
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||||
|
"Lapp/revanced/extension/youtube/patches/OpenVideosFullscreen;"
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val openVideosFullscreenPatch = bytecodePatch(
|
||||||
|
name = "Open videos fullscreen",
|
||||||
|
description = "Adds an option to open videos in full screen portrait mode.",
|
||||||
|
) {
|
||||||
|
dependsOn(
|
||||||
|
sharedExtensionPatch,
|
||||||
|
settingsPatch,
|
||||||
|
addResourcesPatch,
|
||||||
|
)
|
||||||
|
|
||||||
|
compatibleWith(
|
||||||
|
"com.google.android.youtube"(
|
||||||
|
"19.46.42",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
execute {
|
||||||
|
openVideosFullscreenPortraitFingerprint.method.insertFeatureFlagBooleanOverride(
|
||||||
|
OPEN_VIDEOS_FULLSCREEN_PORTRAIT_FEATURE_FLAG,
|
||||||
|
"$EXTENSION_CLASS_DESCRIPTOR->openVideoFullscreenPortrait(Z)Z"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Add resources and setting last, in case the user force patches an old incompatible version.
|
||||||
|
|
||||||
|
addResources("youtube", "layout.player.fullscreen.openVideosFullscreen")
|
||||||
|
|
||||||
|
PreferenceScreen.PLAYER.addPreferences(
|
||||||
|
SwitchPreference("revanced_open_videos_fullscreen_portrait")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@ import app.revanced.util.getReference
|
|||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
||||||
import app.revanced.util.inputStreamFromBundledResource
|
import app.revanced.util.inputStreamFromBundledResource
|
||||||
|
import app.revanced.util.insertFeatureFlagBooleanOverride
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
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.TwoRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||||
@@ -228,19 +229,10 @@ val seekbarColorPatch = bytecodePatch(
|
|||||||
|
|
||||||
// 19.25+ changes
|
// 19.25+ changes
|
||||||
|
|
||||||
playerSeekbarGradientConfigFingerprint.method.apply {
|
playerSeekbarGradientConfigFingerprint.method.insertFeatureFlagBooleanOverride(
|
||||||
val literalIndex = indexOfFirstLiteralInstructionOrThrow(PLAYER_SEEKBAR_GRADIENT_FEATURE_FLAG)
|
PLAYER_SEEKBAR_GRADIENT_FEATURE_FLAG,
|
||||||
val resultIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT)
|
"$EXTENSION_CLASS_DESCRIPTOR->playerSeekbarGradientEnabled(Z)Z"
|
||||||
val register = getInstruction<OneRegisterInstruction>(resultIndex).registerA
|
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
resultIndex + 1,
|
|
||||||
"""
|
|
||||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->playerSeekbarGradientEnabled(Z)Z
|
|
||||||
move-result v$register
|
|
||||||
"""
|
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
lithoLinearGradientFingerprint.method.addInstruction(
|
lithoLinearGradientFingerprint.method.addInstruction(
|
||||||
0,
|
0,
|
||||||
@@ -255,20 +247,11 @@ val seekbarColorPatch = bytecodePatch(
|
|||||||
launchScreenLayoutTypeFingerprint,
|
launchScreenLayoutTypeFingerprint,
|
||||||
mainActivityOnCreateFingerprint
|
mainActivityOnCreateFingerprint
|
||||||
).forEach { fingerprint ->
|
).forEach { fingerprint ->
|
||||||
fingerprint.method.apply {
|
fingerprint.method.insertFeatureFlagBooleanOverride(
|
||||||
val literalIndex = indexOfFirstLiteralInstructionOrThrow(launchScreenLayoutTypeLotteFeatureFlag)
|
launchScreenLayoutTypeLotteFeatureFlag,
|
||||||
val resultIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT)
|
"$EXTENSION_CLASS_DESCRIPTOR->useLotteLaunchSplashScreen(Z)Z"
|
||||||
val register = getInstruction<OneRegisterInstruction>(resultIndex).registerA
|
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
resultIndex + 1,
|
|
||||||
"""
|
|
||||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->useLotteLaunchSplashScreen(Z)Z
|
|
||||||
move-result v$register
|
|
||||||
"""
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Hook the splash animation drawable to set the a seekbar color theme.
|
// Hook the splash animation drawable to set the a seekbar color theme.
|
||||||
mainActivityOnCreateFingerprint.method.apply {
|
mainActivityOnCreateFingerprint.method.apply {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package app.revanced.patches.youtube.layout.theme
|
package app.revanced.patches.youtube.layout.theme
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
|
||||||
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.patcher.patch.resourcePatch
|
import app.revanced.patcher.patch.resourcePatch
|
||||||
@@ -17,10 +16,7 @@ import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
|||||||
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
|
||||||
import app.revanced.util.forEachChildElement
|
import app.revanced.util.forEachChildElement
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.insertFeatureFlagBooleanOverride
|
||||||
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
|
|
||||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||||
@@ -212,19 +208,10 @@ val themePatch = bytecodePatch(
|
|||||||
SwitchPreference("revanced_gradient_loading_screen"),
|
SwitchPreference("revanced_gradient_loading_screen"),
|
||||||
)
|
)
|
||||||
|
|
||||||
useGradientLoadingScreenFingerprint.method.apply {
|
useGradientLoadingScreenFingerprint.method.insertFeatureFlagBooleanOverride(
|
||||||
val literalIndex = indexOfFirstLiteralInstructionOrThrow(GRADIENT_LOADING_SCREEN_AB_CONSTANT)
|
GRADIENT_LOADING_SCREEN_AB_CONSTANT,
|
||||||
val isEnabledIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT)
|
"$EXTENSION_CLASS_DESCRIPTOR->gradientLoadingScreenEnabled(Z)Z"
|
||||||
val isEnabledRegister = getInstruction<OneRegisterInstruction>(isEnabledIndex).registerA
|
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
isEnabledIndex + 1,
|
|
||||||
"""
|
|
||||||
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->gradientLoadingScreenEnabled()Z
|
|
||||||
move-result v$isEnabledRegister
|
|
||||||
""",
|
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
mapOf(
|
mapOf(
|
||||||
themeHelperLightColorFingerprint to lightThemeBackgroundColor,
|
themeHelperLightColorFingerprint to lightThemeBackgroundColor,
|
||||||
|
|||||||
@@ -34,10 +34,7 @@ internal val disableCairoSettingsPatch = bytecodePatch(
|
|||||||
* <a href="https://github.com/qnblackcat/uYouPlus/issues/1468">uYouPlus#1468</a>.
|
* <a href="https://github.com/qnblackcat/uYouPlus/issues/1468">uYouPlus#1468</a>.
|
||||||
*/
|
*/
|
||||||
cairoFragmentConfigFingerprint.method.apply {
|
cairoFragmentConfigFingerprint.method.apply {
|
||||||
val literalIndex = indexOfFirstLiteralInstructionOrThrow(
|
val literalIndex = indexOfFirstLiteralInstructionOrThrow(CAIRO_CONFIG_LITERAL_VALUE)
|
||||||
CAIRO_CONFIG_LITERAL_VALUE,
|
|
||||||
)
|
|
||||||
|
|
||||||
val resultIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT)
|
val resultIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT)
|
||||||
val register = getInstruction<OneRegisterInstruction>(resultIndex).registerA
|
val register = getInstruction<OneRegisterInstruction>(resultIndex).registerA
|
||||||
|
|
||||||
|
|||||||
@@ -40,10 +40,7 @@ val spoofVideoStreamsPatch = spoofVideoStreamsPatch({
|
|||||||
"revanced_spoof_video_streams_client",
|
"revanced_spoof_video_streams_client",
|
||||||
summaryKey = null,
|
summaryKey = null,
|
||||||
),
|
),
|
||||||
SwitchPreference(
|
SwitchPreference("revanced_spoof_video_streams_ios_force_avc"),
|
||||||
"revanced_spoof_video_streams_ios_force_avc",
|
|
||||||
tag = "app.revanced.extension.youtube.settings.preference.ForceAVCSpoofingPreference",
|
|
||||||
),
|
|
||||||
NonInteractivePreference("revanced_spoof_video_streams_about_android_vr"),
|
NonInteractivePreference("revanced_spoof_video_streams_about_android_vr"),
|
||||||
NonInteractivePreference("revanced_spoof_video_streams_about_ios"),
|
NonInteractivePreference("revanced_spoof_video_streams_about_ios"),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import app.revanced.patches.shared.misc.mapping.resourceMappings
|
|||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.Method
|
import com.android.tools.smali.dexlib2.iface.Method
|
||||||
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.ReferenceInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.Reference
|
import com.android.tools.smali.dexlib2.iface.reference.Reference
|
||||||
@@ -402,6 +403,20 @@ fun Method.findInstructionIndicesReversedOrThrow(opcode: Opcode): List<Int> {
|
|||||||
return instructions
|
return instructions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun MutableMethod.insertFeatureFlagBooleanOverride(literal: Long, extensionsMethod: String) {
|
||||||
|
val literalIndex = indexOfFirstLiteralInstructionOrThrow(literal)
|
||||||
|
val index = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT)
|
||||||
|
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||||
|
|
||||||
|
addInstructions(
|
||||||
|
index + 1,
|
||||||
|
"""
|
||||||
|
invoke-static { v$register }, $extensionsMethod
|
||||||
|
move-result v$register
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called for _all_ instructions with the given literal value.
|
* Called for _all_ instructions with the given literal value.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -11,6 +11,116 @@
|
|||||||
<item>ANDROID_VR</item>
|
<item>ANDROID_VR</item>
|
||||||
<item>IOS</item>
|
<item>IOS</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
<string-array name="revanced_spoof_video_streams_language_entries">
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_DEFAULT</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_AR</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_AZ</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_BG</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_BN</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_CA</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_CS</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_DA</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_DE</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_EL</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_EN</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_ES</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_ET</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_FA</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_FI</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_FR</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_GU</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_HI</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_HR</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_HU</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_ID</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_IT</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_JA</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_KK</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_KO</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_LT</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_LV</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_MK</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_MN</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_MR</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_MS</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_MY</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_NL</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_OR</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_PA</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_PL</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_PT_BR</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_PT_PT</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_RO</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_RU</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_SK</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_SL</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_SR</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_SV</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_SW</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_TA</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_TE</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_TH</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_TR</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_UK</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_UR</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_VI</item>
|
||||||
|
<item>@string/revanced_spoof_video_streams_language_ZH</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="revanced_spoof_video_streams_language_entry_values">
|
||||||
|
<item>DEFAULT</item>
|
||||||
|
<item>AR</item>
|
||||||
|
<item>AZ</item>
|
||||||
|
<item>BG</item>
|
||||||
|
<item>BN</item>
|
||||||
|
<item>CA</item>
|
||||||
|
<item>CS</item>
|
||||||
|
<item>DA</item>
|
||||||
|
<item>DE</item>
|
||||||
|
<item>EL</item>
|
||||||
|
<item>EN</item>
|
||||||
|
<item>ES</item>
|
||||||
|
<item>ET</item>
|
||||||
|
<item>FA</item>
|
||||||
|
<item>FI</item>
|
||||||
|
<item>FR</item>
|
||||||
|
<item>GU</item>
|
||||||
|
<item>HI</item>
|
||||||
|
<item>HR</item>
|
||||||
|
<item>HU</item>
|
||||||
|
<item>ID</item>
|
||||||
|
<item>IT</item>
|
||||||
|
<item>JA</item>
|
||||||
|
<item>KK</item>
|
||||||
|
<item>KO</item>
|
||||||
|
<item>LT</item>
|
||||||
|
<item>LV</item>
|
||||||
|
<item>MK</item>
|
||||||
|
<item>MN</item>
|
||||||
|
<item>MR</item>
|
||||||
|
<item>MS</item>
|
||||||
|
<item>MY</item>
|
||||||
|
<item>NL</item>
|
||||||
|
<item>OR</item>
|
||||||
|
<item>PA</item>
|
||||||
|
<item>PL</item>
|
||||||
|
<item>PT_BR</item>
|
||||||
|
<item>PT_PT</item>
|
||||||
|
<item>RO</item>
|
||||||
|
<item>RU</item>
|
||||||
|
<item>SK</item>
|
||||||
|
<item>SL</item>
|
||||||
|
<item>SR</item>
|
||||||
|
<item>SV</item>
|
||||||
|
<item>SW</item>
|
||||||
|
<item>TA</item>
|
||||||
|
<item>TE</item>
|
||||||
|
<item>TH</item>
|
||||||
|
<item>TR</item>
|
||||||
|
<item>UK</item>
|
||||||
|
<item>UR</item>
|
||||||
|
<item>VI</item>
|
||||||
|
<item>ZH</item>
|
||||||
|
</string-array>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="layout.spoofappversion.spoofAppVersionPatch">
|
<patch id="layout.spoofappversion.spoofAppVersionPatch">
|
||||||
<string-array name="revanced_spoof_app_version_target_entries">
|
<string-array name="revanced_spoof_app_version_target_entries">
|
||||||
|
|||||||
@@ -715,6 +715,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
|||||||
<string name="revanced_hide_player_popup_panels_summary_on">Player popup panels are hidden</string>
|
<string name="revanced_hide_player_popup_panels_summary_on">Player popup panels are hidden</string>
|
||||||
<string name="revanced_hide_player_popup_panels_summary_off">Player popup panels are shown</string>
|
<string name="revanced_hide_player_popup_panels_summary_off">Player popup panels are shown</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
<patch id="layout.player.fullscreen.openVideosFullscreen">
|
||||||
|
<string name="revanced_open_videos_fullscreen_portrait_title">Open videos in fullscreen portrait</string>
|
||||||
|
<string name="revanced_open_videos_fullscreen_portrait_summary_on">Videos open fullscreen</string>
|
||||||
|
<string name="revanced_open_videos_fullscreen_portrait_summary_off">Videos do not open fullscreen</string>
|
||||||
|
</patch>
|
||||||
<patch id="layout.player.overlay.customPlayerOverlayOpacityResourcePatch">
|
<patch id="layout.player.overlay.customPlayerOverlayOpacityResourcePatch">
|
||||||
<string name="revanced_player_overlay_opacity_title">Player overlay opacity</string>
|
<string name="revanced_player_overlay_opacity_title">Player overlay opacity</string>
|
||||||
<string name="revanced_player_overlay_opacity_summary">Opacity value between 0-100, where 0 is transparent</string>
|
<string name="revanced_player_overlay_opacity_summary">Opacity value between 0-100, where 0 is transparent</string>
|
||||||
@@ -1220,14 +1225,68 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
|||||||
<string name="revanced_spoof_video_streams_user_dialog_message">Turning off this setting may cause video playback issues.</string>
|
<string name="revanced_spoof_video_streams_user_dialog_message">Turning off this setting may cause video playback issues.</string>
|
||||||
<string name="revanced_spoof_video_streams_client_title">Default client</string>
|
<string name="revanced_spoof_video_streams_client_title">Default client</string>
|
||||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">Force AVC (H.264)</string>
|
<string name="revanced_spoof_video_streams_ios_force_avc_title">Force AVC (H.264)</string>
|
||||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">Video codec is AVC (H.264)</string>
|
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">Video codec is forced to AVC (H.264)</string>
|
||||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">Video codec is VP9 or AV1</string>
|
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">Video codec is determined automatically</string>
|
||||||
<string name="revanced_spoof_video_streams_ios_force_avc_no_hardware_vp9_summary_on">Your device does not have VP9 hardware decoding, and this setting is always on when Client spoofing is enabled</string>
|
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">Enabling this might improve battery life and fix playback stuttering.\n\nAVC has a maximum resolution of 1080p, Opus audio codec is not available, and video playback will use more internet data than VP9 or AV1.</string>
|
||||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">Enabling this might improve battery life and fix playback stuttering.\n\nAVC has a maximum resolution of 1080p, and video playback will use more internet data than VP9 or AV1.</string>
|
|
||||||
<string name="revanced_spoof_video_streams_about_ios_title">iOS spoofing side effects</string>
|
<string name="revanced_spoof_video_streams_about_ios_title">iOS spoofing side effects</string>
|
||||||
<string name="revanced_spoof_video_streams_about_ios_summary">• Private kids videos may not play\n• Livestreams start from the beginning\n• Videos may end 1 second early</string>
|
<string name="revanced_spoof_video_streams_about_ios_summary">• Private kids videos may not play\n• Livestreams start from the beginning\n• Videos may end 1 second early</string>
|
||||||
<string name="revanced_spoof_video_streams_about_android_vr_title">Android VR spoofing side effects</string>
|
<string name="revanced_spoof_video_streams_about_android_vr_title">Android VR spoofing side effects</string>
|
||||||
<string name="revanced_spoof_video_streams_about_android_vr_summary">• Kids videos may not play\n• Audio track menu is missing\n• Stable volume is not available</string>
|
<string name="revanced_spoof_video_streams_about_android_vr_summary">• Kids videos may not play\n• Audio track menu is missing\n• Stable volume is not available</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_">Video streams are spoofed</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_title">Preferred audio stream language</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_DEFAULT">App language</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_AR">Arabic</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_AZ">Azerbaijani</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_BG">Bulgarian</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_BN">Bengali</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_CA">Catalan</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_CS">Czech</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_DA">Danish</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_DE">German</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_EL">Greek</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_EN">English</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_ES">Spanish</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_ET">Estonian</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_FA">Persian</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_FI">Finnish</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_FR">French</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_GU">Gujarati</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_HI">Hindi</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_HR">Croatian</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_HU">Hungarian</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_ID">Indonesian</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_IT">Italian</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_JA">Japanese</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_KK">Kazakh</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_KO">Korean</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_LT">Lithuanian</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_LV">Latvian</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_MK">Macedonian</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_MN">Mongolian</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_MR">Marathi</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_MS">Malay</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_MY">Burmese</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_NL">Dutch</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_OR">Odia</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_PA">Punjabi</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_PL">Polish</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_PT_BR">Portuguese (Brazil)</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_PT_PT">Portuguese (Portugal)</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_RO">Romanian</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_RU">Russian</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_SK">Slovak</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_SL">Slovene</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_SR">Serbian</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_SV">Swedish</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_SW">Swahili</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_TA">Tamil</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_TE">Telugu</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_TH">Thai</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_TR">Turkish</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_UK">Ukrainian</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_UR">Urdu</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_VI">Vietnamese</string>
|
||||||
|
<string name="revanced_spoof_video_streams_language_ZH">Chinese</string>
|
||||||
</patch>
|
</patch>
|
||||||
</app>
|
</app>
|
||||||
<app id="twitch">
|
<app id="twitch">
|
||||||
|
|||||||
Reference in New Issue
Block a user