Skip to content

Commit

Permalink
chore: Merge branch dev to main (#4123)
Browse files Browse the repository at this point in the history
oSumAtrIX authored Dec 16, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents ea90c57 + 0b2a10f commit ccea384
Showing 111 changed files with 3,016 additions and 787 deletions.
42 changes: 42 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,45 @@
# [5.5.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.5.0-dev.4...v5.5.0-dev.5) (2024-12-16)


### Features

* **YouTube - Navigation buttons:** Add options to disable translucent status bar and navigation bar ([#4133](https://github.com/ReVanced/revanced-patches/issues/4133)) ([a2d2141](https://github.com/ReVanced/revanced-patches/commit/a2d2141cec9b0b4929e07a8010889b21c324b229))

# [5.5.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.5.0-dev.3...v5.5.0-dev.4) (2024-12-16)


### Bug Fixes

* **YouTube - Spoof video streams:** Make livestreams start at the current time when using iOS client ([#4137](https://github.com/ReVanced/revanced-patches/issues/4137)) ([140f484](https://github.com/ReVanced/revanced-patches/commit/140f484b4b251b0dfa94163a63f61f45f5302052))

# [5.5.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.5.0-dev.2...v5.5.0-dev.3) (2024-12-16)


### Features

* **YouTube - Hide feed components:** Remove obsolete `Hide search result shelf header` option ([#4134](https://github.com/ReVanced/revanced-patches/issues/4134)) ([c71443a](https://github.com/ReVanced/revanced-patches/commit/c71443a08883ab10ef2553213c03b00e7c580a43))

# [5.5.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.5.0-dev.1...v5.5.0-dev.2) (2024-12-16)


### Bug Fixes

* **YouTube Music:** Add `Spoof client patch` to fix playback ([#4132](https://github.com/ReVanced/revanced-patches/issues/4132)) ([b092508](https://github.com/ReVanced/revanced-patches/commit/b0925088e8b41636e285cb234593d545604ce461))

# [5.5.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.4.1-dev.1...v5.5.0-dev.1) (2024-12-15)


### Features

* **YouTube:** Add `Force original audio` patch ([#4122](https://github.com/ReVanced/revanced-patches/issues/4122)) ([f4aa440](https://github.com/ReVanced/revanced-patches/commit/f4aa4406080b91f01d623e54b11b99ea849ddcdf))

## [5.4.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.4.0...v5.4.1-dev.1) (2024-12-14)


### Bug Fixes

* **Twitch:** Change recommended target to the latest app version ([fb32972](https://github.com/ReVanced/revanced-patches/commit/fb32972f4de92dac1fc5d73f56a392a671c4e94b))

# [5.4.0](https://github.com/ReVanced/revanced-patches/compare/v5.3.0...v5.4.0) (2024-12-14)


1 change: 1 addition & 0 deletions extensions/music/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// Do not remove. Necessary for the extension plugin to be applied to the project.
1 change: 1 addition & 0 deletions extensions/music/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<manifest/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package app.revanced.extension.music.spoof;

/**
* @noinspection unused
*/
public class SpoofClientPatch {
private static final int CLIENT_TYPE_ID = 26;
private static final String CLIENT_VERSION = "6.21";
private static final String DEVICE_MODEL = "iPhone16,2";
private static final String OS_VERSION = "17.7.2.21H221";

public static int getClientId() {
return CLIENT_TYPE_ID;
}

public static String getClientVersion() {
return CLIENT_VERSION;
}

public static String getClientModel() {
return DEVICE_MODEL;
}

public static String getOsVersion() {
return OS_VERSION;
}
}
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import static app.revanced.extension.shared.settings.Setting.parent;
import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.ForceiOSAVCAvailability;
import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.SpoofiOSAvailability;

import app.revanced.extension.shared.spoof.AudioStreamLanguage;
import app.revanced.extension.shared.spoof.ClientType;
@@ -22,9 +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 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, parent(SPOOF_VIDEO_STREAMS));
public static final EnumSetting<AudioStreamLanguage> SPOOF_VIDEO_STREAMS_LANGUAGE = new EnumSetting<>("revanced_spoof_video_streams_language", AudioStreamLanguage.DEFAULT, new SpoofiOSAvailability());
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 ForceiOSAVCAvailability());
"revanced_spoof_video_streams_ios_force_avc_user_dialog_message", new SpoofiOSAvailability());
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));

}
Original file line number Diff line number Diff line change
@@ -3,6 +3,11 @@
import java.util.Locale;

public enum AudioStreamLanguage {
/**
* YouTube default.
* Can be the original language or can be app language,
* depending on what YouTube decides to pick as the default.
*/
DEFAULT,

// Language codes found in locale_config.xml
@@ -86,15 +91,21 @@ public enum AudioStreamLanguage {
private final String iso639_1;

AudioStreamLanguage() {
iso639_1 = name().replace('_', '-');
String name = name();
final int regionSeparatorIndex = name.indexOf('_');
if (regionSeparatorIndex >= 0) {
iso639_1 = name.substring(0, regionSeparatorIndex).toLowerCase(Locale.US)
+ name.substring(regionSeparatorIndex);
} else {
iso639_1 = name().toLowerCase(Locale.US);
}
}

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 Locale.getDefault().toLanguageTag();
}

return iso639_1;
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ public enum ClientType {
"32", // Android 12.1
"1.56.21",
true,
true),
false),
// Specific for kids videos.
IOS(5,
"IOS",
@@ -40,21 +40,8 @@ public enum ClientType {
? "17.40.5"
: "19.47.7",
false,
true),
/**
* Android VR with no language code.
* Used for age restricted videos and YouTube Music to disable stable volume.
*/
ANDROID_VR_NO_HL(
ANDROID_VR.id,
ANDROID_VR.clientName,
ANDROID_VR.deviceModel,
ANDROID_VR.osVersion,
ANDROID_VR.userAgent,
ANDROID_VR.androidSdkVersion,
ANDROID_VR.clientVersion,
ANDROID_VR.canLogin,
false);
true
);

private static boolean forceAVC() {
return BaseSettings.SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC.get();
Original file line number Diff line number Diff line change
@@ -16,20 +16,16 @@
@SuppressWarnings("unused")
public class SpoofVideoStreamsPatch {
private static final boolean SPOOF_STREAMING_DATA = BaseSettings.SPOOF_VIDEO_STREAMS.get();

private static final boolean FIX_HLS_CURRENT_TIME = SPOOF_STREAMING_DATA
&& BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS;

/**
* Any unreachable ip address. Used to intentionally fail requests.
*/
private static final String UNREACHABLE_HOST_URI_STRING = "https://127.0.0.0";
private static final Uri UNREACHABLE_HOST_URI = Uri.parse(UNREACHABLE_HOST_URI_STRING);

/**
* Injection point. Used by YT Music to disable stable volume.
*/
public static void setClientTypeToAndroidVrNoHl() {
Logger.printDebug(() -> "Setting stream spoofing to: " + ClientType.ANDROID_VR_NO_HL);
BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.save(ClientType.ANDROID_VR_NO_HL);
}

/**
* Injection point.
* Blocks /get_watch requests by returning an unreachable URI.
@@ -173,10 +169,24 @@ public static byte[] removeVideoPlaybackPostBody(Uri uri, int method, byte[] pos
return postData;
}

public static final class ForceiOSAVCAvailability implements Setting.Availability {
/**
* Injection point.
*
* Fixes iOS livestreams starting from the beginning.
*/
public static boolean fixHLSCurrentTime(boolean original) {
if (FIX_HLS_CURRENT_TIME) {
return false;
}

return original;
}

public static final class SpoofiOSAvailability implements Setting.Availability {
@Override
public boolean isAvailable() {
return BaseSettings.SPOOF_VIDEO_STREAMS.get() && BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS;
return BaseSettings.SPOOF_VIDEO_STREAMS.get()
&& BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS;
}
}
}
Original file line number Diff line number Diff line change
@@ -19,7 +19,9 @@ final class PlayerRoutes {
"?fields=streamingData" +
"&alt=proto"
).compile();

private static final String YT_API_URL = "https://youtubei.googleapis.com/youtubei/v1/";

/**
* TCP connection and HTTP read timeout
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package app.revanced.extension.youtube.patches;

import app.revanced.extension.shared.Logger;
import app.revanced.extension.youtube.settings.Settings;

@SuppressWarnings("unused")
public class ForceOriginalAudioPatch {

private static final String DEFAULT_AUDIO_TRACKS_IDENTIFIER = "original";

/**
* Injection point.
*/
public static boolean isDefaultAudioStream(boolean isDefault, String audioTrackId, String audioTrackDisplayName) {
try {
if (!Settings.FORCE_ORIGINAL_AUDIO.get()) {
return isDefault;
}

if (audioTrackDisplayName.isEmpty()) {
// Older app targets can have empty audio tracks and these might be placeholders.
// The real audio tracks are called after these.
return isDefault;
}

Logger.printDebug(() -> "default: " + String.format("%-5s", isDefault) + " id: "
+ String.format("%-8s", audioTrackId) + " name:" + audioTrackDisplayName);

final boolean isOriginal = audioTrackDisplayName.contains(DEFAULT_AUDIO_TRACKS_IDENTIFIER);
if (isOriginal) {
Logger.printDebug(() -> "Using audio: " + audioTrackId);
}

return isOriginal;
} catch (Exception ex) {
Logger.printException(() -> "isDefaultAudioStream failure", ex);
}

return isDefault;
}
}
Original file line number Diff line number Diff line change
@@ -3,12 +3,15 @@
import static app.revanced.extension.shared.Utils.hideViewUnderCondition;
import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButton;

import android.os.Build;
import android.view.View;

import java.util.EnumMap;
import java.util.Map;

import android.widget.TextView;

import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.settings.Settings;

@SuppressWarnings("unused")
@@ -26,6 +29,15 @@ public final class NavigationButtonsPatch {
private static final boolean SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON
= Settings.SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON.get();

private static final Boolean DISABLE_TRANSLUCENT_STATUS_BAR
= Settings.DISABLE_TRANSLUCENT_STATUS_BAR.get();

private static final Boolean DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT
= Settings.DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT.get();

private static final Boolean DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK
= Settings.DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK.get();

/**
* Injection point.
*/
@@ -48,4 +60,42 @@ public static void navigationTabCreated(NavigationButton button, View tabView) {
public static void hideNavigationButtonLabels(TextView navigationLabelsView) {
hideViewUnderCondition(Settings.HIDE_NAVIGATION_BUTTON_LABELS, navigationLabelsView);
}

/**
* Injection point.
*/
public static boolean useTranslucentNavigationStatusBar(boolean original) {
// Must check Android version, as forcing this on Android 11 or lower causes app hang and crash.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
return original;
}

if (DISABLE_TRANSLUCENT_STATUS_BAR) {
return false;
}

return original;
}

/**
* Injection point.
*/
public static boolean useTranslucentNavigationButtons(boolean original) {
// Feature requires Android 13+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
return original;
}

if (!DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK && !DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT) {
return original;
}

if (DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK && DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT) {
return false;
}

return Utils.isDarkModeEnabled(Utils.getContext())
? !DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK
: !DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT;
}
}
Original file line number Diff line number Diff line change
@@ -36,7 +36,6 @@ public final class LayoutComponentsFilter extends Filter {
);

private final StringTrieSearch exceptions = new StringTrieSearch();
private final StringFilterGroup searchResultShelfHeader;
private final StringFilterGroup inFeedSurvey;
private final StringFilterGroup notifyMe;
private final StringFilterGroup expandableMetadata;
@@ -194,11 +193,6 @@ public LayoutComponentsFilter() {
"timed_reaction"
);

searchResultShelfHeader = new StringFilterGroup(
Settings.HIDE_SEARCH_RESULT_SHELF_HEADER,
"shelf_header.eml"
);

notifyMe = new StringFilterGroup(
Settings.HIDE_NOTIFY_ME_BUTTON,
"set_reminder_button"
@@ -324,9 +318,6 @@ boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBuff
return false;
}

// TODO: This also hides the feed Shorts shelf header
if (matchedGroup == searchResultShelfHeader && contentIndex != 0) return false;

if (matchedGroup == horizontalShelves) {
if (contentIndex == 0 && hideShelves()) {
return super.isFiltered(path, identifier, protobufBufferArray, matchedGroup, contentType, contentIndex);
Original file line number Diff line number Diff line change
@@ -16,7 +16,6 @@
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MODERN_2;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MODERN_3;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MODERN_4;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.PHONE;
import static app.revanced.extension.youtube.patches.SeekbarThumbnailsPatch.SeekbarThumbnailsHighQualityAvailability;
import static app.revanced.extension.youtube.patches.VersionCheckPatch.IS_19_17_OR_GREATER;
import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.IGNORE;
@@ -52,6 +51,8 @@ public class Settings extends BaseSettings {
public static final FloatSetting PLAYBACK_SPEED_DEFAULT = new FloatSetting("revanced_playback_speed_default", -2.0f);
public static final StringSetting CUSTOM_PLAYBACK_SPEEDS = new StringSetting("revanced_custom_playback_speeds",
"0.25\n0.5\n0.75\n0.9\n0.95\n1.0\n1.05\n1.1\n1.25\n1.5\n1.75\n2.0\n3.0\n4.0\n5.0", true);
// Audio
public static final BooleanSetting FORCE_ORIGINAL_AUDIO = new BooleanSetting("revanced_force_original_audio", FALSE);

// Ads
public static final BooleanSetting HIDE_BUTTONED_ADS = new BooleanSetting("revanced_hide_buttoned_ads", TRUE);
@@ -91,7 +92,6 @@ public class Settings extends BaseSettings {
public static final BooleanSetting HIDE_NOTIFY_ME_BUTTON = new BooleanSetting("revanced_hide_notify_me_button", TRUE);
public static final BooleanSetting HIDE_PLAYABLES = new BooleanSetting("revanced_hide_playables", TRUE);
public static final BooleanSetting HIDE_SEARCH_RESULT_RECOMMENDATIONS = new BooleanSetting("revanced_hide_search_result_recommendations", TRUE);
public static final BooleanSetting HIDE_SEARCH_RESULT_SHELF_HEADER = new BooleanSetting("revanced_hide_search_result_shelf_header", FALSE);
public static final BooleanSetting HIDE_SHOW_MORE_BUTTON = new BooleanSetting("revanced_hide_show_more_button", TRUE, true);
// Alternative thumbnails
public static final EnumSetting<ThumbnailOption> ALT_THUMBNAIL_HOME = new EnumSetting<>("revanced_alt_thumbnail_home", ThumbnailOption.ORIGINAL);
@@ -217,6 +217,9 @@ public class Settings extends BaseSettings {
public static final BooleanSetting HIDE_SUBSCRIPTIONS_BUTTON = new BooleanSetting("revanced_hide_subscriptions_button", FALSE, true);
public static final BooleanSetting HIDE_NAVIGATION_BUTTON_LABELS = new BooleanSetting("revanced_hide_navigation_button_labels", FALSE, true);
public static final BooleanSetting SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON = new BooleanSetting("revanced_switch_create_with_notifications_button", TRUE, true);
public static final BooleanSetting DISABLE_TRANSLUCENT_STATUS_BAR = new BooleanSetting("revanced_disable_translucent_status_bar", FALSE, true);
public static final BooleanSetting DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT = new BooleanSetting("revanced_disable_translucent_navigation_bar_light", FALSE, true);
public static final BooleanSetting DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK = new BooleanSetting("revanced_disable_translucent_navigation_bar_dark", FALSE, true);

// Shorts
public static final BooleanSetting DISABLE_RESUMING_SHORTS_PLAYER = new BooleanSetting("revanced_disable_resuming_shorts_player", FALSE);
@@ -388,7 +391,8 @@ public class Settings extends BaseSettings {
}

// Migrate renamed enum.
if (MINIPLAYER_TYPE.get() == PHONE) {
//noinspection deprecation
if (MINIPLAYER_TYPE.get() == MiniplayerType.PHONE) {
MINIPLAYER_TYPE.save(MINIMAL);
}

Original file line number Diff line number Diff line change
@@ -48,35 +48,44 @@ public static Drawable getBackButtonDrawable() {

/**
* Sorts a preference list by menu entries, but preserves the first value as the first entry.
*
* @noinspection SameParameterValue
*/
private static void sortListPreferenceByValues(ListPreference listPreference) {
private static void sortListPreferenceByValues(ListPreference listPreference, int firstEntriesToPreserve) {
CharSequence[] entries = listPreference.getEntries();
CharSequence[] entryValues = listPreference.getEntryValues();
final int entrySize = entries.length;

if (entrySize != entryValues.length) {
// Xml array declaration has a missing/extra entry.
throw new IllegalStateException();
}

// Ensure the first entry remains the first after sorting.
CharSequence firstEntry = entries[0];
CharSequence firstEntryValue = entryValues[0];
List<Pair<String, String>> firstPairs = new ArrayList<>(firstEntriesToPreserve);
List<Pair<String, String>> pairsToSort = new ArrayList<>(entrySize);

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()));
for (int i = 0; i < entrySize; i++) {
Pair<String, String> pair = new Pair<>(entries[i].toString(), entryValues[i].toString());
if (i < firstEntriesToPreserve) {
firstPairs.add(pair);
} else {
pairsToSort.add(pair);
}
}

Collections.sort(entryPairs, (pair1, pair2) -> pair1.first.compareToIgnoreCase(pair2.first));
Collections.sort(pairsToSort, (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 = 0;
for (Pair<String, String> pair : firstPairs) {
sortedEntries[i] = pair.first;
sortedEntryValues[i] = pair.second;
i++;
}

int i = 1;
for (Pair<String, String> pair : entryPairs) {
for (Pair<String, String> pair : pairsToSort) {
sortedEntries[i] = pair.first;
sortedEntryValues[i] = pair.second;
i++;
@@ -102,7 +111,7 @@ protected void initialize() {

preference = findPreference(Settings.SPOOF_VIDEO_STREAMS_LANGUAGE.key);
if (preference instanceof ListPreference languagePreference) {
sortListPreferenceByValues(languagePreference);
sortListPreferenceByValues(languagePreference, 1);
}
} catch (Exception ex) {
Logger.printException(() -> "initialize failure", ex);
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
org.gradle.parallel = true
android.useAndroidX = true
kotlin.code.style = official
version = 5.4.0
version = 5.5.0-dev.5
16 changes: 14 additions & 2 deletions patches/api/patches.api
Original file line number Diff line number Diff line change
@@ -324,8 +324,12 @@ public final class app/revanced/patches/music/misc/gms/GmsCoreSupportPatchKt {
public static final fun getGmsCoreSupportPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}

public final class app/revanced/patches/music/misc/spoof/SpoofVideoStreamsPatchKt {
public static final fun getSpoofVideoStreamsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
public final class app/revanced/patches/music/misc/spoof/SpoofClientPatchKt {
public static final fun getSpoofClientPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}

public final class app/revanced/patches/music/misc/spoof/UserAgentClientSpoofPatchKt {
public static final fun getUserAgentClientSpoofPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}

public final class app/revanced/patches/myexpenses/misc/pro/UnlockProPatchKt {
@@ -766,6 +770,10 @@ public final class app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatch
public static synthetic fun spoofVideoStreamsPatch$default (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/BytecodePatch;
}

public final class app/revanced/patches/shared/misc/spoof/UserAgentClientSpoofPatchKt {
public static final fun userAgentClientSpoofPatch (Ljava/lang/String;)Lapp/revanced/patcher/patch/BytecodePatch;
}

public final class app/revanced/patches/solidexplorer2/functionality/filesize/RemoveFileSizeLimitPatchKt {
public static final fun getRemoveFileSizeLimitPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -1392,6 +1400,10 @@ public final class app/revanced/patches/youtube/shared/FingerprintsKt {
public static final fun getRollingNumberTextViewAnimationUpdateFingerprint ()Lapp/revanced/patcher/Fingerprint;
}

public final class app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatchKt {
public static final fun getForceOriginalAudioPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}

public final class app/revanced/patches/youtube/video/information/VideoInformationPatchKt {
public static final fun getVideoInformationPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun userSelectedPlaybackSpeedHook (Ljava/lang/String;Ljava/lang/String;)V
Original file line number Diff line number Diff line change
@@ -4,5 +4,6 @@ import app.revanced.patches.music.misc.extension.hooks.applicationInitHook
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch

val sharedExtensionPatch = sharedExtensionPatch(
"music",
applicationInitHook,
)
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ import app.revanced.patcher.patch.Option
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_NAME
import app.revanced.patches.music.misc.gms.Constants.REVANCED_MUSIC_PACKAGE_NAME
import app.revanced.patches.music.misc.spoof.spoofVideoStreamsPatch
import app.revanced.patches.music.misc.spoof.spoofClientPatch
import app.revanced.patches.shared.castContextFetchFingerprint
import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch
import app.revanced.patches.shared.primeMethodFingerprint
@@ -21,7 +21,7 @@ val gmsCoreSupportPatch = gmsCoreSupportPatch(
extensionPatch = sharedExtensionPatch,
gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch,
) {
dependsOn(spoofVideoStreamsPatch)
dependsOn(spoofClientPatch)

compatibleWith(MUSIC_PACKAGE_NAME)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package app.revanced.patches.music.misc.spoof

import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode

internal val playerRequestConstructorFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
strings("player")
}

/**
* Matches using the class found in [playerRequestConstructorFingerprint].
*/
internal val createPlayerRequestBodyFingerprint = fingerprint {
parameters("L")
returns("V")
opcodes(
Opcode.CHECK_CAST,
Opcode.IGET,
Opcode.AND_INT_LIT16,
)
strings("ms")
}

/**
* Used to get a reference to other clientInfo fields.
*/
internal val setClientInfoFieldsFingerprint = fingerprint {
returns("L")
strings("Google Inc.")
}

/**
* Used to get a reference to the clientInfo and clientInfo.clientVersion field.
*/
internal val setClientInfoClientVersionFingerprint = fingerprint {
strings("10.29")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package app.revanced.patches.music.misc.spoof

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.instructions
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.util.getReference
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter

internal const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/music/spoof/SpoofClientPatch;"

// TODO: Replace this patch with spoofVideoStreamsPatch once possible.
val spoofClientPatch = bytecodePatch(
name = "Spoof client",
description = "Spoofs the client to fix playback.",
) {
compatibleWith("com.google.android.apps.youtube.music")

dependsOn(
sharedExtensionPatch,
// TODO: Add settingsPatch
userAgentClientSpoofPatch,
)

execute {
val playerRequestClass = playerRequestConstructorFingerprint.classDef

val createPlayerRequestBodyMatch = createPlayerRequestBodyFingerprint.match(playerRequestClass)

val clientInfoContainerClass = createPlayerRequestBodyMatch.method
.getInstruction(createPlayerRequestBodyMatch.patternMatch!!.startIndex)
.getReference<TypeReference>()!!.type

val clientInfoField = setClientInfoClientVersionFingerprint.method.instructions.first {
it.opcode == Opcode.IPUT_OBJECT && it.getReference<FieldReference>()!!.definingClass == clientInfoContainerClass
}.getReference<FieldReference>()!!

val setClientInfoFieldInstructions = setClientInfoFieldsFingerprint.method.instructions.filter {
(it.opcode == Opcode.IPUT_OBJECT || it.opcode == Opcode.IPUT) &&
it.getReference<FieldReference>()!!.definingClass == clientInfoField.type
}.map { it.getReference<FieldReference>()!! }

// Offsets are known for the fields in the clientInfo object.
val clientIdField = setClientInfoFieldInstructions[0]
val clientModelField = setClientInfoFieldInstructions[5]
val osVersionField = setClientInfoFieldInstructions[7]
val clientVersionField = setClientInfoClientVersionFingerprint.method
.getInstruction(setClientInfoClientVersionFingerprint.stringMatches!!.first().index + 1)
.getReference<FieldReference>()

// Helper method to spoof the client info.
val spoofClientInfoMethod = ImmutableMethod(
playerRequestClass.type,
"spoofClientInfo",
listOf(ImmutableMethodParameter(clientInfoContainerClass, null, null)),
"V",
AccessFlags.PRIVATE.value or AccessFlags.STATIC.value,
null,
null,
MutableMethodImplementation(3),
).toMutable().also(playerRequestClass.methods::add).apply {
addInstructions(
"""
iget-object v0, p0, $clientInfoField
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->getClientId()I
move-result v1
iput v1, v0, $clientIdField
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->getClientModel()Ljava/lang/String;
move-result-object v1
iput-object v1, v0, $clientModelField
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->getClientVersion()Ljava/lang/String;
move-result-object v1
iput-object v1, v0, $clientVersionField
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->getOsVersion()Ljava/lang/String;
move-result-object v1
iput-object v1, v0, $osVersionField
return-void
""",
)
}

createPlayerRequestBodyMatch.method.apply {
val checkCastIndex = createPlayerRequestBodyMatch.patternMatch!!.startIndex
val clientInfoContainerRegister = getInstruction<OneRegisterInstruction>(checkCastIndex).registerA

addInstruction(checkCastIndex + 1, "invoke-static {v$clientInfoContainerRegister}, $spoofClientInfoMethod")
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package app.revanced.patches.music.misc.spoof

import app.revanced.patches.shared.misc.spoof.userAgentClientSpoofPatch

val userAgentClientSpoofPatch = userAgentClientSpoofPatch("com.google.android.apps.youtube.music")
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package app.revanced.patches.shared.misc.spoof

import app.revanced.patcher.fingerprint
import app.revanced.util.literal
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode

@@ -110,3 +111,13 @@ internal val buildMediaDataSourceFingerprint = fingerprint {
"Ljava/lang/Object;",
)
}

internal const val HLS_CURRENT_TIME_FEATURE_FLAG = 45355374L

internal val hlsCurrentTimeFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
parameters("Z", "L")
literal {
HLS_CURRENT_TIME_FEATURE_FLAG
}
}
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMu
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.insertFeatureFlagBooleanOverride
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
@@ -201,6 +202,15 @@ fun spoofVideoStreamsPatch(
}
// endregion

// region Fix iOS livestream current time.

hlsCurrentTimeFingerprint.method.insertFeatureFlagBooleanOverride(
HLS_CURRENT_TIME_FEATURE_FLAG,
"$EXTENSION_CLASS_DESCRIPTOR->fixHLSCurrentTime(Z)Z"
)

// endregion

executeBlock()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package app.revanced.patches.shared.misc.spoof

import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patches.all.misc.transformation.IMethodCall
import app.revanced.patches.all.misc.transformation.filterMapInstruction35c
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.StringReference

private const val USER_AGENT_STRING_BUILDER_APPEND_METHOD_REFERENCE =
"Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;"

fun userAgentClientSpoofPatch(originalPackageName: String) = transformInstructionsPatch(
filterMap = { classDef, _, instruction, instructionIndex ->
filterMapInstruction35c<MethodCall>(
"Lapp/revanced/extension",
classDef,
instruction,
instructionIndex,
)
},
transform = transform@{ mutableMethod, entry ->
val (_, _, instructionIndex) = entry

// Replace the result of context.getPackageName(), if it is used in a user agent string.
mutableMethod.apply {
// After context.getPackageName() the result is moved to a register.
val targetRegister = (
getInstruction(instructionIndex + 1)
as? OneRegisterInstruction ?: return@transform
).registerA

// IndexOutOfBoundsException is technically possible here,
// but no such occurrences are present in the app.
val referee = getInstruction(instructionIndex + 2).getReference<MethodReference>()?.toString()

// Only replace string builder usage.
if (referee != USER_AGENT_STRING_BUILDER_APPEND_METHOD_REFERENCE) {
return@transform
}

// Do not change the package name in methods that use resources, or for methods that use GmsCore.
// Changing these package names will result in playback limitations,
// particularly Android VR background audio only playback.
val resourceOrGmsStringInstructionIndex = indexOfFirstInstruction {
val reference = getReference<StringReference>()
opcode == Opcode.CONST_STRING &&
(reference?.string == "android.resource://" || reference?.string == "gcore_")
}
if (resourceOrGmsStringInstructionIndex >= 0) {
return@transform
}

// Overwrite the result of context.getPackageName() with the original package name.
replaceInstruction(
instructionIndex + 1,
"const-string v$targetRegister, \"$originalPackageName\"",
)
}
},
)

@Suppress("unused")
private enum class MethodCall(
override val definedClassName: String,
override val methodName: String,
override val methodParams: Array<String>,
override val returnType: String,
) : IMethodCall {
GetPackageName(
"Landroid/content/Context;",
"getPackageName",
emptyArray(),
"Ljava/lang/String;",
),
}
Original file line number Diff line number Diff line change
@@ -156,10 +156,6 @@ val videoAdsPatch = bytecodePatch(
)

compatibleWith(
"tv.twitch.android.app"(
"15.4.1",
"16.1.0",
"16.9.1",
),
"tv.twitch.android.app",
)
}
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ package app.revanced.patches.youtube.layout.buttons.navigation
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.AccessFlags
import app.revanced.patcher.fingerprint
import app.revanced.util.literal

internal const val ANDROID_AUTOMOTIVE_STRING = "Android Automotive"

@@ -22,4 +23,31 @@ internal val createPivotBarFingerprint = fingerprint {
Opcode.INVOKE_VIRTUAL,
Opcode.RETURN_VOID,
)
}

internal const val TRANSLUCENT_NAVIGATION_STATUS_BAR_FEATURE_FLAG = 45400535L

internal val translucentNavigationStatusBarFeatureFlagFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("Z")
literal { TRANSLUCENT_NAVIGATION_STATUS_BAR_FEATURE_FLAG }
}

internal const val TRANSLUCENT_NAVIGATION_BUTTONS_FEATURE_FLAG = 45630927L

internal val translucentNavigationButtonsFeatureFlagFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("V")
literal { TRANSLUCENT_NAVIGATION_BUTTONS_FEATURE_FLAG }
}

/**
* The device on screen back/home/recent buttons.
*/
internal const val TRANSLUCENT_NAVIGATION_BUTTONS_SYSTEM_FEATURE_FLAG = 45632194L

internal val translucentNavigationButtonsSystemFeatureFlagFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("Z")
literal { TRANSLUCENT_NAVIGATION_BUTTONS_SYSTEM_FEATURE_FLAG }
}
Original file line number Diff line number Diff line change
@@ -12,10 +12,13 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.navigation.hookNavigationButtonCreated
import app.revanced.patches.youtube.misc.navigation.navigationBarHookPatch
import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.insertFeatureFlagBooleanOverride
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@@ -32,6 +35,7 @@ val navigationButtonsPatch = bytecodePatch(
settingsPatch,
addResourcesPatch,
navigationBarHookPatch,
versionCheckPatch
)

compatibleWith(
@@ -50,19 +54,27 @@ val navigationButtonsPatch = bytecodePatch(
execute {
addResources("youtube", "layout.buttons.navigation.navigationButtonsPatch")

val preferences = mutableSetOf(
SwitchPreference("revanced_hide_home_button"),
SwitchPreference("revanced_hide_shorts_button"),
SwitchPreference("revanced_hide_create_button"),
SwitchPreference("revanced_hide_subscriptions_button"),
SwitchPreference("revanced_switch_create_with_notifications_button"),
SwitchPreference("revanced_hide_navigation_button_labels"),
)

if (is_19_25_or_greater) {
preferences += SwitchPreference("revanced_disable_translucent_status_bar")
preferences += SwitchPreference("revanced_disable_translucent_navigation_bar_light")
preferences += SwitchPreference("revanced_disable_translucent_navigation_bar_dark")
}

PreferenceScreen.GENERAL_LAYOUT.addPreferences(
PreferenceScreenPreference(
key = "revanced_navigation_buttons_screen",
sorting = Sorting.UNSORTED,
preferences = setOf(
SwitchPreference("revanced_hide_home_button"),
SwitchPreference("revanced_hide_shorts_button"),
SwitchPreference("revanced_hide_create_button"),
SwitchPreference("revanced_hide_subscriptions_button"),
SwitchPreference("revanced_switch_create_with_notifications_button"),
SwitchPreference("revanced_hide_navigation_button_labels"),
),
),
preferences = preferences
)
)

// Switch create with notifications button.
@@ -101,5 +113,24 @@ val navigationButtonsPatch = bytecodePatch(

// Hook navigation button created, in order to hide them.
hookNavigationButtonCreated(EXTENSION_CLASS_DESCRIPTOR)


// Force on/off translucent effect on status bar and navigation buttons.
if (is_19_25_or_greater) {
translucentNavigationStatusBarFeatureFlagFingerprint.method.insertFeatureFlagBooleanOverride(
TRANSLUCENT_NAVIGATION_STATUS_BAR_FEATURE_FLAG,
"$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationStatusBar(Z)Z",
)

translucentNavigationButtonsFeatureFlagFingerprint.method.insertFeatureFlagBooleanOverride(
TRANSLUCENT_NAVIGATION_BUTTONS_FEATURE_FLAG,
"$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationButtons(Z)Z",
)

translucentNavigationButtonsSystemFeatureFlagFingerprint.method.insertFeatureFlagBooleanOverride(
TRANSLUCENT_NAVIGATION_BUTTONS_SYSTEM_FEATURE_FLAG,
"$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationButtons(Z)Z",
)
}
}
}
Original file line number Diff line number Diff line change
@@ -222,7 +222,6 @@ val hideLayoutComponentsPatch = bytecodePatch(
SwitchPreference("revanced_hide_notify_me_button"),
SwitchPreference("revanced_hide_playables"),
SwitchPreference("revanced_hide_search_result_recommendations"),
SwitchPreference("revanced_hide_search_result_shelf_header"),
SwitchPreference("revanced_hide_show_more_button"),
SwitchPreference("revanced_hide_doodles"),
)
Original file line number Diff line number Diff line change
@@ -110,22 +110,22 @@ val enableDebuggingPatch = bytecodePatch(
"""
)
}
}

experimentalStringFeatureFlagFingerprint.match(
experimentalFeatureFlagParentFingerprint.originalClassDef
).method.apply {
val insertIndex = indexOfFirstInstructionReversedOrThrow(Opcode.MOVE_RESULT_OBJECT)
experimentalStringFeatureFlagFingerprint.match(
experimentalFeatureFlagParentFingerprint.originalClassDef
).method.apply {
val insertIndex = indexOfFirstInstructionReversedOrThrow(Opcode.MOVE_RESULT_OBJECT)

addInstructions(
insertIndex,
"""
move-result-object v0
invoke-static { v0, p1, p2, p3 }, $EXTENSION_CLASS_DESCRIPTOR->isStringFeatureFlagEnabled(Ljava/lang/String;JLjava/lang/String;)Ljava/lang/String;
move-result-object v0
return-object v0
"""
)
addInstructions(
insertIndex,
"""
move-result-object v0
invoke-static { v0, p1, p2, p3 }, $EXTENSION_CLASS_DESCRIPTOR->isStringFeatureFlagEnabled(Ljava/lang/String;JLjava/lang/String;)Ljava/lang/String;
move-result-object v0
return-object v0
"""
)
}
}

// There exists other experimental accessor methods for byte[]
Original file line number Diff line number Diff line change
@@ -1,82 +1,5 @@
package app.revanced.patches.youtube.misc.spoof

import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patches.all.misc.transformation.IMethodCall
import app.revanced.patches.all.misc.transformation.filterMapInstruction35c
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.StringReference
import app.revanced.patches.shared.misc.spoof.userAgentClientSpoofPatch

private const val ORIGINAL_PACKAGE_NAME = "com.google.android.youtube"
private const val USER_AGENT_STRING_BUILDER_APPEND_METHOD_REFERENCE =
"Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;"

val userAgentClientSpoofPatch = transformInstructionsPatch(
filterMap = { classDef, _, instruction, instructionIndex ->
filterMapInstruction35c<MethodCall>(
"Lapp/revanced/extension",
classDef,
instruction,
instructionIndex,
)
},
transform = transform@{ mutableMethod, entry ->
val (_, _, instructionIndex) = entry

// Replace the result of context.getPackageName(), if it is used in a user agent string.
mutableMethod.apply {
// After context.getPackageName() the result is moved to a register.
val targetRegister = (
getInstruction(instructionIndex + 1)
as? OneRegisterInstruction ?: return@transform
).registerA

// IndexOutOfBoundsException is technically possible here,
// but no such occurrences are present in the app.
val referee = getInstruction(instructionIndex + 2).getReference<MethodReference>()?.toString()

// Only replace string builder usage.
if (referee != USER_AGENT_STRING_BUILDER_APPEND_METHOD_REFERENCE) {
return@transform
}

// Do not change the package name in methods that use resources, or for methods that use GmsCore.
// Changing these package names will result in playback limitations,
// particularly Android VR background audio only playback.
val resourceOrGmsStringInstructionIndex = indexOfFirstInstruction {
val reference = getReference<StringReference>()
opcode == Opcode.CONST_STRING &&
(reference?.string == "android.resource://" || reference?.string == "gcore_")
}
if (resourceOrGmsStringInstructionIndex >= 0) {
return@transform
}

// Overwrite the result of context.getPackageName() with the original package name.
replaceInstruction(
instructionIndex + 1,
"const-string v$targetRegister, \"$ORIGINAL_PACKAGE_NAME\"",
)
}
},
)

@Suppress("unused")
private enum class MethodCall(
override val definedClassName: String,
override val methodName: String,
override val methodParams: Array<String>,
override val returnType: String,
) : IMethodCall {
GetPackageName(
"Landroid/content/Context;",
"getPackageName",
emptyArray(),
"Ljava/lang/String;",
),
}
val userAgentClientSpoofPatch = userAgentClientSpoofPatch("com.google.android.youtube")
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package app.revanced.patches.youtube.video.audio

import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.AccessFlags

internal val streamingModelBuilderFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("L")
strings("vprng")
}

internal val menuItemAudioTrackFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
parameters("L")
returns("V")
strings("menu_item_audio_track")
}

internal val audioStreamingTypeSelector = fingerprint {
accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL)
returns("L")
strings("raw") // String is not unique
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package app.revanced.patches.youtube.video.audio

import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
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.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.immutable.ImmutableField
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter

private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/ForceOriginalAudioPatch;"

@Suppress("unused")
val forceOriginalAudioPatch = bytecodePatch(
name = "Force original audio",
description = "Adds an option to always use the original audio track.",
) {
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",
),
)

execute {
addResources("youtube", "video.audio.forceOriginalAudioPatch")

PreferenceScreen.VIDEO.addPreferences(
SwitchPreference("revanced_force_original_audio")
)

fun Method.firstFormatStreamingModelCall(
returnType: String = "Ljava/lang/String;"
): MutableMethod {
val audioTrackIdIndex = indexOfFirstInstructionOrThrow {
val reference = getReference<MethodReference>()
reference?.definingClass == "Lcom/google/android/libraries/youtube/innertube/model/media/FormatStreamModel;"
&& reference.returnType == returnType
}

return navigate(this).to(audioTrackIdIndex).stop()
}

// Accessor methods of FormatStreamModel have no string constants and
// opcodes are identical to other methods in the same class,
// so must walk from another class that use the methods.
val isDefaultMethod = streamingModelBuilderFingerprint.originalMethod.firstFormatStreamingModelCall("Z")
val audioTrackIdMethod = menuItemAudioTrackFingerprint.originalMethod.firstFormatStreamingModelCall()
val audioTrackDisplayNameMethod = audioStreamingTypeSelector.originalMethod.firstFormatStreamingModelCall()
val formatStreamModelClass = proxy(classes.first {
it.type == audioTrackIdMethod.definingClass
}).mutableClass

formatStreamModelClass.apply {
// Add a new field to store the override.
val helperFieldName = "isDefaultAudioTrackOverride"
fields.add(
ImmutableField(
type,
helperFieldName,
"Ljava/lang/Boolean;",
// Boolean is a 100% immutable class (all fields are final)
// and safe to write to a shared field without volatile/synchronization,
// but without volatile the field can show stale data
// and the same field is calculated more than once by different threads.
AccessFlags.PRIVATE.value or AccessFlags.VOLATILE.value,
null,
null,
null
).toMutable()
)

// Add a helper method because the isDefaultAudioTrack() has only 2 registers and 3 are needed.
val helperMethodClass = type
val helperMethodName = "extension_isDefaultAudioTrack"
val helperMethod = ImmutableMethod(
helperMethodClass,
helperMethodName,
listOf(ImmutableMethodParameter("Z", null, null)),
"Z",
AccessFlags.PRIVATE.value,
null,
null,
MutableMethodImplementation(6),
).toMutable().apply {
addInstructionsWithLabels(
0,
"""
iget-object v0, p0, $helperMethodClass->$helperFieldName:Ljava/lang/Boolean;
if-eqz v0, :call_extension
invoke-virtual { v0 }, Ljava/lang/Boolean;->booleanValue()Z
move-result v3
return v3
:call_extension
invoke-virtual { p0 }, $audioTrackIdMethod
move-result-object v1
invoke-virtual { p0 }, $audioTrackDisplayNameMethod
move-result-object v2
invoke-static { p1, v1, v2 }, $EXTENSION_CLASS_DESCRIPTOR->isDefaultAudioStream(ZLjava/lang/String;Ljava/lang/String;)Z
move-result v3
invoke-static { v3 }, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;
move-result-object v0
iput-object v0, p0, $helperMethodClass->$helperFieldName:Ljava/lang/Boolean;
return v3
"""
)
}
methods.add(helperMethod)

// Modify isDefaultAudioTrack() to call extension helper method.
isDefaultMethod.apply {
val index = indexOfFirstInstructionOrThrow(Opcode.RETURN)
val register = getInstruction<OneRegisterInstruction>(index).registerA

addInstructions(
index,
"""
invoke-direct { p0, v$register }, $helperMethodClass->$helperMethodName(Z)Z
move-result v$register
"""
)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -200,6 +200,8 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.zoomhaptics.zoomHapticsPatch">
</patch>
<patch id="video.audio.forceOriginalAudioPatch">
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as revanced_custom_playback_speeds_auto -->
</patch>
Original file line number Diff line number Diff line change
@@ -200,6 +200,8 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.zoomhaptics.zoomHapticsPatch">
</patch>
<patch id="video.audio.forceOriginalAudioPatch">
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as revanced_custom_playback_speeds_auto -->
</patch>
19 changes: 13 additions & 6 deletions patches/src/main/resources/addresources/values-ar-rSA/strings.xml
Original file line number Diff line number Diff line change
@@ -33,6 +33,7 @@ Second \"item\" text"</string>
<string name="revanced_check_environment_not_near_patch_time_invalid">تاريخ إنشاء APK تالف</string>
</patch>
<patch id="misc.settings.settingsResourcePatch">
<string name="revanced_settings_title">ReVanced</string>
<string name="revanced_settings_confirm_user_dialog_title">هل ترغب في المتابعة؟</string>
<string name="revanced_settings_reset">إعادة التعيين</string>
<string name="revanced_settings_restart_title">تحديث وإعادة تشغيل</string>
@@ -78,6 +79,7 @@ Second \"item\" text"</string>
<string name="revanced_settings_screen_03_feed_title">الموجز</string>
<string name="revanced_settings_screen_04_player_title">المشغل</string>
<string name="revanced_settings_screen_05_general_title">التصميم العام</string>
<string name="revanced_settings_screen_06_shorts_title">Shorts</string>
<string name="revanced_settings_screen_07_seekbar_title">شريط تقدم الفيديو</string>
<string name="revanced_settings_screen_08_swipe_controls_title">التحكم عن طريق إيماءة التمرير</string>
<string name="revanced_settings_screen_11_misc_title">إعدادات متنوعة</string>
@@ -157,9 +159,6 @@ Second \"item\" text"</string>
<string name="revanced_hide_timed_reactions_title">إخفاء ردود الفعل المؤقتة</string>
<string name="revanced_hide_timed_reactions_summary_on">تم إخفاء ردود الفعل المؤقتة</string>
<string name="revanced_hide_timed_reactions_summary_off">يتم عرض ردود الفعل المؤقتة</string>
<string name="revanced_hide_search_result_shelf_header_title">إخفاء رأس رف نتائج البحث</string>
<string name="revanced_hide_search_result_shelf_header_summary_on">تم إخفاء رأس الرف</string>
<string name="revanced_hide_search_result_shelf_header_summary_off">يتم عرض رأس الرف</string>
<string name="revanced_hide_channel_guidelines_title">إخفاء إرشادات القناة</string>
<string name="revanced_hide_channel_guidelines_summary_on">تم إخفاء إرشادات القناة</string>
<string name="revanced_hide_channel_guidelines_summary_off">يتم عرض إرشادات القناة</string>
@@ -517,6 +516,10 @@ Second \"item\" text"</string>
<string name="revanced_hide_navigation_button_labels_title">إخفاء تسميات زر التنقل</string>
<string name="revanced_hide_navigation_button_labels_summary_on">تم إخفاء التسميات</string>
<string name="revanced_hide_navigation_button_labels_summary_off">يتم عرض التسميات</string>
<string name="revanced_disable_translucent_status_bar_title">تعطيل شريط الحالة الشفاف</string>
<string name="revanced_disable_translucent_navigation_bar_light_title">تعطيل شريط التنقل الشفاف الفاتح</string>
<string name="revanced_disable_translucent_navigation_bar_light_summary_on">شريط التنقل في الوضع الفاتح معتم</string>
<string name="revanced_disable_translucent_navigation_bar_dark_summary_on">شريط التنقل في الوضع الداكن معتم</string>
</patch>
<patch id="layout.hide.player.flyoutmenupanel.hidePlayerFlyoutMenuPatch">
<string name="revanced_hide_player_flyout_title">القائمة المنبثقة</string>
@@ -1215,6 +1218,11 @@ Second \"item\" text"</string>
<string name="revanced_disable_zoom_haptics_summary_on">تم تعطيل الاهتزاز</string>
<string name="revanced_disable_zoom_haptics_summary_off">تم تمكين الاهتزاز</string>
</patch>
<patch id="video.audio.forceOriginalAudioPatch">
<string name="revanced_force_original_audio_title">فرض الصوت الأصلي</string>
<string name="revanced_force_original_audio_summary_on">استخدام الصوت الأصلي</string>
<string name="revanced_force_original_audio_summary_off">استخدام الصوت الافتراضي</string>
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as revanced_custom_playback_speeds_auto -->
<string name="revanced_video_quality_default_entry_1">تلقائي</string>
@@ -1276,9 +1284,8 @@ Second \"item\" text"</string>

يتمتع تنسيق AVC بدقة قصوى تبلغ 1080P، برنامج ترميز الصوت Opus غير متوفر، وسيستخدم تشغيل الفيديو المزيد من بيانات الإنترنت مقارنةً بتنسيق VP9 أو AV1."</string>
<string name="revanced_spoof_video_streams_about_ios_title">التأثيرات الجانبية لمحاكاة iOS</string>
<string name="revanced_spoof_video_streams_about_ios_summary">"• قد لا يتم تشغيل فيديوهات الأطفال الخاصة
• تبدأ البثوث المباشرة من البداية
• قد تنتهي الفيديوهات قبل النهاية بثانية واحدة"</string>
<string name="revanced_spoof_video_streams_about_ios_summary">"• لا يمكن تشغيل مقاطع فيديو الأطفال الخاصة.
• تنتهي مقاطع الفيديو مبكرًا بمقدار 1 ثانية."</string>
<string name="revanced_spoof_video_streams_about_android_vr_title">التأثيرات الجانبية لمحاكاة Android VR</string>
<string name="revanced_spoof_video_streams_about_android_vr_summary">"• قد لا يتم تشغيل فيديوهات الأطفال
• تبدأ البثوث المباشرة من البداية
Original file line number Diff line number Diff line change
@@ -183,8 +183,10 @@ Second \"item\" text"</string>
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
</patch>
<patch id="misc.announcements.announcementsPatch">
<string name="revanced_announcements_dialog_dismiss">খাৰিজ কৰক</string>
</patch>
<patch id="misc.dns.checkWatchHistoryDomainNameResolutionPatch">
<string name="revanced_check_watch_history_domain_name_dialog_title">সকীয়নি</string>
</patch>
<patch id="misc.autorepeat.autoRepeatPatch">
</patch>
@@ -200,6 +202,8 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.zoomhaptics.zoomHapticsPatch">
</patch>
<patch id="video.audio.forceOriginalAudioPatch">
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as revanced_custom_playback_speeds_auto -->
</patch>
27 changes: 20 additions & 7 deletions patches/src/main/resources/addresources/values-az-rAZ/strings.xml
Original file line number Diff line number Diff line change
@@ -33,6 +33,7 @@ Second \"item\" text"</string>
<string name="revanced_check_environment_not_near_patch_time_invalid">APK quruluş tarixi pozulub</string>
</patch>
<patch id="misc.settings.settingsResourcePatch">
<string name="revanced_settings_title">\"ReVanced\"</string>
<string name="revanced_settings_confirm_user_dialog_title">Davam etmək istəyirsiniz?</string>
<string name="revanced_settings_reset">Sıfırla</string>
<string name="revanced_settings_restart_title">Yenilə və yenidən başlat</string>
@@ -78,10 +79,11 @@ Davam düyməsinə toxunun və optimallaşdırma dəyişikliklərinə icazə ver
<string name="revanced_settings_screen_03_feed_title">Axın</string>
<string name="revanced_settings_screen_04_player_title">Oynadıcı</string>
<string name="revanced_settings_screen_05_general_title">Ümumi tərtibat</string>
<string name="revanced_settings_screen_06_shorts_title">\"Shorts\"</string>
<string name="revanced_settings_screen_07_seekbar_title">Axtarış çubuğu</string>
<string name="revanced_settings_screen_08_swipe_controls_title">Sürüşdürmə nəzarətçiləri</string>
<string name="revanced_settings_screen_11_misc_title">Müxtəlif</string>
<string name="revanced_settings_screen_12_video_title">Video</string>
<string name="revanced_settings_screen_12_video_title">\"Video\"</string>
</patch>
<patch id="misc.backgroundplayback.backgroundPlaybackPatch">
<string name="revanced_shorts_disable_background_playback_title">Shorts arxa plan oynatmasın bağla</string>
@@ -157,9 +159,6 @@ Gözlənilməz tədbirlər barədə bildiriş almayacaqsınız."</string>
<string name="revanced_hide_timed_reactions_title">Vaxtlı reaksiyaları gizlət</string>
<string name="revanced_hide_timed_reactions_summary_on">Zamanlanmış reaksiyalar gizlədilir</string>
<string name="revanced_hide_timed_reactions_summary_off">Zamanlanmış reaksiyalar göstərilir</string>
<string name="revanced_hide_search_result_shelf_header_title">Axtarış nəticəsi bölmə başlığını gizlət</string>
<string name="revanced_hide_search_result_shelf_header_summary_on">Bölmə başlığı gizlidir</string>
<string name="revanced_hide_search_result_shelf_header_summary_off">Bölmə başlığı göstərilir</string>
<string name="revanced_hide_channel_guidelines_title">Kanal təlimatlarını gizlət</string>
<string name="revanced_hide_channel_guidelines_summary_on">Kanal təlimatları gizlidir</string>
<string name="revanced_hide_channel_guidelines_summary_off">Kanal təlimatları göstərilir</string>
@@ -517,6 +516,15 @@ Qeyd: Bunu aktivləşdirmək video reklamları da məcburi olaraq gizlədir"</st
<string name="revanced_hide_navigation_button_labels_title">Fəaliyyət düymə etiketlərini gizlət</string>
<string name="revanced_hide_navigation_button_labels_summary_on">Etiketlər gizlidir</string>
<string name="revanced_hide_navigation_button_labels_summary_off">Etiketlər göstərilir</string>
<string name="revanced_disable_translucent_status_bar_title">Yarımşəffaf status barı deaktiv et</string>
<string name="revanced_disable_translucent_status_bar_summary_on">Status çubuğu şəffaf deyil</string>
<string name="revanced_disable_translucent_status_bar_summary_off">Status çubuğu şəffaf və ya yarı şəffaf</string>
<string name="revanced_disable_translucent_navigation_bar_light_title">Açıq yarımşəffaf barı deaktiv et</string>
<string name="revanced_disable_translucent_navigation_bar_light_summary_on">Açıq rejim navigasiya barı qeyri-şəffafdır</string>
<string name="revanced_disable_translucent_navigation_bar_light_summary_off">Açıq rəngli naviqasiya çubuğu şəffaf və ya yarı şəffaf</string>
<string name="revanced_disable_translucent_navigation_bar_dark_title">Tünd şəffaf çubuğu deaktiv edin</string>
<string name="revanced_disable_translucent_navigation_bar_dark_summary_on">Tünd rejim navigasiya barı qeyri-şəffafdır</string>
<string name="revanced_disable_translucent_navigation_bar_dark_summary_off">Tünd rəngli naviqasiya çubuğu şəffaf və ya yarı şəffaf</string>
</patch>
<patch id="layout.hide.player.flyoutmenupanel.hidePlayerFlyoutMenuPatch">
<string name="revanced_hide_player_flyout_title">Açılan menyu</string>
@@ -1140,6 +1148,7 @@ Bunu aktivləşdirmək, bəzi regionlarda bloklanmışdırılmış itkin şəkil
<string name="revanced_alt_thumbnail_options_entry_2">DeArrow &amp; Orijinal miniatürlər</string>
<string name="revanced_alt_thumbnail_options_entry_3">DeArrow &amp; Kadr çəkilişlər</string>
<string name="revanced_alt_thumbnail_options_entry_4">Kadr çəkilişləri</string>
<string name="revanced_alt_thumbnail_dearrow_about_title">DeArrow</string>
<string name="revanced_alt_thumbnail_dearrow_about_summary">"DeArrow, YouTube videoları üçün kütlədən alınan kiçik görüntülər təqdim edir. Bu kiçik görüntülər YouTube tərəfindən təqdim edilənlərdən daha uyğun ola bilər

Aktivləşdirilərsə, video URLləri API serverinə göndəriləcək və başqa heç bir məlumat göndərilməyəcək. Bir videoda DeArrow kiçik şəkilləri yoxdursa, onda orijinal və ya hərəkətsiz çəkilişlər göstərilir
@@ -1215,6 +1224,11 @@ Bunu aktivləşdirmə daha yüksək video keyfiyyətləri əngəlin silə bilər
<string name="revanced_disable_zoom_haptics_summary_on">Toxunuş əks-əlaqəsi bağlandı</string>
<string name="revanced_disable_zoom_haptics_summary_off">Toxunuş əks-əlaqəsi aktivdir</string>
</patch>
<patch id="video.audio.forceOriginalAudioPatch">
<string name="revanced_force_original_audio_title">Orijinal səsi tələb et</string>
<string name="revanced_force_original_audio_summary_on">Orijinal səs istifadəsi</string>
<string name="revanced_force_original_audio_summary_off">İlkin səs istifadəsi</string>
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as revanced_custom_playback_speeds_auto -->
<string name="revanced_video_quality_default_entry_1">Avtomatik</string>
@@ -1276,9 +1290,8 @@ Video oynatma işləməyə bilər"</string>

AVC-nin maksimum dəqiqliyi 1080p-dir, Opus səs kodek əlçatan deyil və video oxutma, VP9 və ya AV1-dən daha çox internet datası istifadə edəcək."</string>
<string name="revanced_spoof_video_streams_about_ios_title">iOS saxtakarlığı yan təsirləri</string>
<string name="revanced_spoof_video_streams_about_ios_summary">"• Şəxsi uşaq videoları oxudulmaya bilər
• Canlı yayımlar başdan başlayır
• Videolar 1 saniyə tez bitir"</string>
<string name="revanced_spoof_video_streams_about_ios_summary">"◦ Xüsusi uşaq videoları bəlkə də oynanılmaya bilər
◦ Videolar 1 saniyə tez bitir"</string>
<string name="revanced_spoof_video_streams_about_android_vr_title">Android VR saxtakarlığı yan təsirləri</string>
<string name="revanced_spoof_video_streams_about_android_vr_summary">"• Uşaq videoları oxudulmaya bilər
• Canlı yayımlar başdan başlayır
18 changes: 12 additions & 6 deletions patches/src/main/resources/addresources/values-be-rBY/strings.xml
Original file line number Diff line number Diff line change
@@ -33,6 +33,7 @@ Second \"item\" text"</string>
<string name="revanced_check_environment_not_near_patch_time_invalid">Дата стварэння APK пашкоджана</string>
</patch>
<patch id="misc.settings.settingsResourcePatch">
<string name="revanced_settings_title">ReVanced</string>
<string name="revanced_settings_confirm_user_dialog_title">Вы хочаце працягнуць?</string>
<string name="revanced_settings_reset">Скінуць</string>
<string name="revanced_settings_restart_title">Абнавіце і перазагрузіце</string>
@@ -78,6 +79,7 @@ Second \"item\" text"</string>
<string name="revanced_settings_screen_03_feed_title">Карміць</string>
<string name="revanced_settings_screen_04_player_title">Гулец</string>
<string name="revanced_settings_screen_05_general_title">Генеральная планіроўка</string>
<string name="revanced_settings_screen_06_shorts_title">Shorts</string>
<string name="revanced_settings_screen_07_seekbar_title">Панэль пошуку</string>
<string name="revanced_settings_screen_08_swipe_controls_title">Элементы кіравання пальцам</string>
<string name="revanced_settings_screen_11_misc_title">Рознае</string>
@@ -157,9 +159,6 @@ Second \"item\" text"</string>
<string name="revanced_hide_timed_reactions_title">Схаваць рэакцыі па часе</string>
<string name="revanced_hide_timed_reactions_summary_on">Часовыя рэакцыі схаваныя</string>
<string name="revanced_hide_timed_reactions_summary_off">Паказваюцца рэакцыі па часе</string>
<string name="revanced_hide_search_result_shelf_header_title">Схаваць загаловак паліцы з вынікамі пошуку</string>
<string name="revanced_hide_search_result_shelf_header_summary_on">Загаловак паліцы схаваны</string>
<string name="revanced_hide_search_result_shelf_header_summary_off">Паказаны загаловак паліцы</string>
<string name="revanced_hide_channel_guidelines_title">Схаваць рэкамендацыі канала</string>
<string name="revanced_hide_channel_guidelines_summary_on">Правілы канала схаваны</string>
<string name="revanced_hide_channel_guidelines_summary_off">Паказваюцца інструкцыі па каналах</string>
@@ -517,6 +516,10 @@ Second \"item\" text"</string>
<string name="revanced_hide_navigation_button_labels_title">Схаваць меткі кнопак навігацыі</string>
<string name="revanced_hide_navigation_button_labels_summary_on">Цэтлікі схаваныя</string>
<string name="revanced_hide_navigation_button_labels_summary_off">Этыкеткі паказаны</string>
<string name="revanced_disable_translucent_status_bar_title">Адключыць празрыстую панэль стану</string>
<string name="revanced_disable_translucent_navigation_bar_light_title">Адключыць светлую празрыстую панэль</string>
<string name="revanced_disable_translucent_navigation_bar_light_summary_on">Панэль навігацыі ў светлым рэжыме непразрыстая</string>
<string name="revanced_disable_translucent_navigation_bar_dark_summary_on">Панэль навігацыі ў цёмным рэжыме непразрыстая</string>
</patch>
<patch id="layout.hide.player.flyoutmenupanel.hidePlayerFlyoutMenuPatch">
<string name="revanced_hide_player_flyout_title">Выпадаючае меню</string>
@@ -1216,6 +1219,11 @@ Second \"item\" text"</string>
<string name="revanced_disable_zoom_haptics_summary_on">Тактыльныя функцыі адключаны</string>
<string name="revanced_disable_zoom_haptics_summary_off">Тактыльныя сігналы ўключаны</string>
</patch>
<patch id="video.audio.forceOriginalAudioPatch">
<string name="revanced_force_original_audio_title">Вымушанае арыгінальнае аўдыё</string>
<string name="revanced_force_original_audio_summary_on">Выкарыстанне арыгінальнага аўдыё</string>
<string name="revanced_force_original_audio_summary_off">Выкарыстанне аўдыё па змаўчанні</string>
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as revanced_custom_playback_speeds_auto -->
<string name="revanced_video_quality_default_entry_1">Аўто</string>
@@ -1225,6 +1233,7 @@ Second \"item\" text"</string>
<string name="revanced_video_quality_default_wifi_title">Стандартная якасць відэа ў сетцы Wi-Fi</string>
<string name="revanced_video_quality_default_mobile_title">Стандартная якасць відэа ў мабільнай сетцы</string>
<string name="revanced_remember_video_quality_mobile">мабільны</string>
<string name="revanced_remember_video_quality_wifi">wi-fi</string>
<string name="revanced_remember_video_quality_toast">Стандартная якасць %1$s зменена на: %2$s</string>
</patch>
<patch id="video.speed.button.playbackSpeedButtonPatch">
@@ -1276,9 +1285,6 @@ Second \"item\" text"</string>

AVC мае максімальную раздзяляльнасць 1080p, аўдыякадэкар Opus недаступны, і відэа будзе выкарыстоўваць больш Інтэрнэт-даных, чым VP9 або AV1."</string>
<string name="revanced_spoof_video_streams_about_ios_title">Пабочныя эфекты падмены iOS</string>
<string name="revanced_spoof_video_streams_about_ios_summary">"• Прыватныя дзіцячыя відэа могуць не прайгравацца
• Трансляцыі ў прамым эфіры пачынаюцца з пачатку
• Відэа заканчваюцца на 1 секунду раней"</string>
<string name="revanced_spoof_video_streams_about_android_vr_title">Побочные эффекты подмены Android VR</string>
<string name="revanced_spoof_video_streams_about_android_vr_summary">"• Дзіцячыя відэа могуць не прайгравацца
• Трансляцыі ў прамым эфіры пачынаюцца з пачатку
Original file line number Diff line number Diff line change
@@ -33,6 +33,7 @@ Second \"item\" text"</string>
<string name="revanced_check_environment_not_near_patch_time_invalid">Датата на компилация на APK е повредена</string>
</patch>
<patch id="misc.settings.settingsResourcePatch">
<string name="revanced_settings_title">ReVanced</string>
<string name="revanced_settings_confirm_user_dialog_title">Искате ли да продължите?</string>
<string name="revanced_settings_reset">Възстанови</string>
<string name="revanced_settings_restart_title">Рестартирай и опресни</string>
@@ -78,6 +79,7 @@ Second \"item\" text"</string>
<string name="revanced_settings_screen_03_feed_title">Поток</string>
<string name="revanced_settings_screen_04_player_title">Плейър</string>
<string name="revanced_settings_screen_05_general_title">Общо оформление</string>
<string name="revanced_settings_screen_06_shorts_title">Шорти</string>
<string name="revanced_settings_screen_07_seekbar_title">Лента за прогрес на видеото</string>
<string name="revanced_settings_screen_08_swipe_controls_title">Контроли с плъзгане</string>
<string name="revanced_settings_screen_11_misc_title">Разни</string>
@@ -157,9 +159,6 @@ Second \"item\" text"</string>
<string name="revanced_hide_timed_reactions_title">Скриване на времевите реакции</string>
<string name="revanced_hide_timed_reactions_summary_on">Времевите реакции са скрити</string>
<string name="revanced_hide_timed_reactions_summary_off">Времевите реакции се показват</string>
<string name="revanced_hide_search_result_shelf_header_title">Скриване на заглавието на рафта с резултатите от търсенето</string>
<string name="revanced_hide_search_result_shelf_header_summary_on">Заглавката на рафта е скрита</string>
<string name="revanced_hide_search_result_shelf_header_summary_off">Заглавката на рафта е показана</string>
<string name="revanced_hide_channel_guidelines_title">Скриване на насоките на канала</string>
<string name="revanced_hide_channel_guidelines_summary_on">Насоките на канала са скрити</string>
<string name="revanced_hide_channel_guidelines_summary_off">Насоките на канала се показват</string>
@@ -516,6 +515,10 @@ Second \"item\" text"</string>
<string name="revanced_hide_navigation_button_labels_title">Имена на бутоните на лентата за навигация</string>
<string name="revanced_hide_navigation_button_labels_summary_on">Етикетите са скрити</string>
<string name="revanced_hide_navigation_button_labels_summary_off">Етикетите се показват</string>
<string name="revanced_disable_translucent_status_bar_title">Деактивирай полупрозрачната лента на състоянието</string>
<string name="revanced_disable_translucent_navigation_bar_light_title">Деактивирай полупрозрачната светла лента за навигация</string>
<string name="revanced_disable_translucent_navigation_bar_light_summary_on">Светлата лента за навигация е непрозрачна</string>
<string name="revanced_disable_translucent_navigation_bar_dark_summary_on">Тъмната лента за навигация е непрозрачна</string>
</patch>
<patch id="layout.hide.player.flyoutmenupanel.hidePlayerFlyoutMenuPatch">
<string name="revanced_hide_player_flyout_title">Падащо меню</string>
@@ -1214,6 +1217,8 @@ Second \"item\" text"</string>
<string name="revanced_disable_zoom_haptics_summary_on">Вибрациите са деактивирани</string>
<string name="revanced_disable_zoom_haptics_summary_off">Вибрациите са активирани</string>
</patch>
<patch id="video.audio.forceOriginalAudioPatch">
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as revanced_custom_playback_speeds_auto -->
<string name="revanced_video_quality_default_entry_1">Авто</string>
@@ -1275,9 +1280,6 @@ Second \"item\" text"</string>

AVC има максимална разделителна способност от 1080p, аудио кодекът Opus не е наличен, а видеовъзпроизвеждането ще използва повече интернет данни от VP9 или AV1."</string>
<string name="revanced_spoof_video_streams_about_ios_title">Cтранични ефекти от подмяната на iOS</string>
<string name="revanced_spoof_video_streams_about_ios_summary">"• Частните детски видеоклипове може да не се възпроизвеждат
• Предаванията на живо започват от началото
• Видеоклиповете завършват 1 секунда по-рано"</string>
<string name="revanced_spoof_video_streams_about_android_vr_title">Странични ефекти от подправяне на Android VR</string>
<string name="revanced_spoof_video_streams_about_android_vr_summary">"• Детските видеоклипове може да не се възпроизвеждат
• Предаванията на живо започват от началото
27 changes: 20 additions & 7 deletions patches/src/main/resources/addresources/values-bn-rBD/strings.xml
Original file line number Diff line number Diff line change
@@ -33,6 +33,7 @@ Second \"item\" text"</string>
<string name="revanced_check_environment_not_near_patch_time_invalid">APK তৈরির তারিখ ত্রুটিপূর্ণ</string>
</patch>
<patch id="misc.settings.settingsResourcePatch">
<string name="revanced_settings_title">ReVanced</string>
<string name="revanced_settings_confirm_user_dialog_title">আপনি কি এগিয়ে যেতে ইচ্ছুক?</string>
<string name="revanced_settings_reset">আবার সেট করুন</string>
<string name="revanced_settings_restart_title">রিফ্রেশ করুন এবং আবার চালু করুন</string>
@@ -78,6 +79,7 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
<string name="revanced_settings_screen_03_feed_title">ফিড</string>
<string name="revanced_settings_screen_04_player_title">প্লেয়ার</string>
<string name="revanced_settings_screen_05_general_title">সাধারণ লে-আউট</string>
<string name="revanced_settings_screen_06_shorts_title">Shorts</string>
<string name="revanced_settings_screen_07_seekbar_title">সিকবার</string>
<string name="revanced_settings_screen_08_swipe_controls_title">সোয়াইপ কন্ট্রোল</string>
<string name="revanced_settings_screen_11_misc_title">বিবিধ</string>
@@ -157,9 +159,6 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
<string name="revanced_hide_timed_reactions_title">সময় অনুযায়ী প্রতিক্রিয়া লুকান</string>
<string name="revanced_hide_timed_reactions_summary_on">সময় অনুযায়ী প্রতিক্রিয়া লুকিয়ে রয়েছে</string>
<string name="revanced_hide_timed_reactions_summary_off">সময় অনুযায়ী প্রতিক্রিয়া প্রদর্শিত হয়েছে</string>
<string name="revanced_hide_search_result_shelf_header_title">অনুসন্ধান ফলাফল শেলফের হেডার লুকান</string>
<string name="revanced_hide_search_result_shelf_header_summary_on">শেলফ হেডার লুকিয়ে রয়েছে</string>
<string name="revanced_hide_search_result_shelf_header_summary_off">শেলফ হেডার প্রদর্শিত হয়েছে</string>
<string name="revanced_hide_channel_guidelines_title">চ্যানেল নির্দেশিকা লুকান</string>
<string name="revanced_hide_channel_guidelines_summary_on">চ্যানেল নির্দেশিকা লুকিয়ে রয়েছে</string>
<string name="revanced_hide_channel_guidelines_summary_off">চ্যানেল নির্দেশিকা প্রদর্শিত হয়েছে</string>
@@ -256,6 +255,7 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">সম্পর্কিত ভিডিওতে প্রদর্শিত হয়েছে</string>
<string name="revanced_comments_screen_title">মন্তব্য</string>
<string name="revanced_comments_screen_summary">মন্তব্য বিভাগের উপাদানগুলি লুকান বা দেখান৷</string>
<string name="revanced_hide_comments_chat_summary_title"> \'চ্যাটের সারাংশ\' লুকান</string>
<string name="revanced_hide_comments_chat_summary_summary_on">“চ্যাট সারাংশ” লুকানো আছে</string>
<string name="revanced_hide_comments_chat_summary_summary_off">“চ্যাট সারাংশ” দেখানো হচ্ছে</string>
<string name="revanced_hide_comments_by_members_header_title">\'মেম্বারদের মন্তব্য\' হেডার লুকান</string>
@@ -445,7 +445,7 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
<string name="revanced_swipe_overlay_background_alpha_title">সোয়াইপ ব্যাকগ্রাউন্ডের দৃশ্যমানতা</string>
<string name="revanced_swipe_overlay_background_alpha_summary">সোয়াইপ ওভারলে ব্যাকগ্রাউন্ডের দৃশ্যমানতা</string>
<string name="revanced_swipe_threshold_title">সোয়াইপ থ্রেশহোল্ড এর মাত্রা</string>
<string name="revanced_swipe_threshold_summary">The amount of threshold for swipe to occur</string>
<string name="revanced_swipe_threshold_summary">সোয়াইপ করার থ্রেশহোল্ডের পরিমাণ</string>
</patch>
<patch id="layout.autocaptions.autoCaptionsPatch">
<string name="revanced_auto_captions_title">স্বয়ংক্রিয় ক্যাপশন বন্ধ করুন</string>
@@ -516,6 +516,15 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
<string name="revanced_hide_navigation_button_labels_title">নেভিগেশন বোতাম লেবেল লুকান</string>
<string name="revanced_hide_navigation_button_labels_summary_on">লেবেল লুকিয়ে রয়েছে</string>
<string name="revanced_hide_navigation_button_labels_summary_off">লেবেল প্রদর্শিত হয়েছে</string>
<string name="revanced_disable_translucent_status_bar_title">অর্ধস্বচ্ছ স্থিতি বার নিষ্ক্রিয় করুন</string>
<string name="revanced_disable_translucent_status_bar_summary_on">স্ট্যাটাস বারটি অস্বচ্ছ</string>
<string name="revanced_disable_translucent_status_bar_summary_off">স্ট্যাটাস বারটি অস্বচ্ছ বা স্বচ্ছ</string>
<string name="revanced_disable_translucent_navigation_bar_light_title">অর্ধস্বচ্ছ হালকা বার নিষ্ক্রিয় করুন</string>
<string name="revanced_disable_translucent_navigation_bar_light_summary_on">হালকা মোড নেভিগেশন বার অস্বচ্ছ</string>
<string name="revanced_disable_translucent_navigation_bar_light_summary_off">লাইট মোড ন্যাভিগেশন বারটি অস্বচ্ছ বা স্বচ্ছ</string>
<string name="revanced_disable_translucent_navigation_bar_dark_title">গাঢ় স্বচ্ছ বার অক্ষম করুন</string>
<string name="revanced_disable_translucent_navigation_bar_dark_summary_on">গাঢ় মোড নেভিগেশন বার অস্বচ্ছ</string>
<string name="revanced_disable_translucent_navigation_bar_dark_summary_off">গাঢ় মোড ন্যাভিগেশন বারটি অস্বচ্ছ বা স্বচ্ছ</string>
</patch>
<patch id="layout.hide.player.flyoutmenupanel.hidePlayerFlyoutMenuPatch">
<string name="revanced_hide_player_flyout_title">ফ্লাইআউট মেনু</string>
@@ -1139,6 +1148,7 @@ Miniplayer স্ক্রিন থেকে বামে বা ডানে
<string name="revanced_alt_thumbnail_options_entry_2">DeArrow এবং মূল থাম্বনেইল</string>
<string name="revanced_alt_thumbnail_options_entry_3">DeArrow এবং স্থির ছবি</string>
<string name="revanced_alt_thumbnail_options_entry_4">স্থির ছবি</string>
<string name="revanced_alt_thumbnail_dearrow_about_title">DeArrow</string>
<string name="revanced_alt_thumbnail_dearrow_about_summary">"DeArrow YouTube ভিডিওগুলির জন্য জনগণের উৎস থেকে তৈরি থাম্বনেইল সরবরাহ করে। এই থাম্বনেইলগুলি প্রায়শই YouTube দ্বারা সরবরাহ করা থাম্বনেইলগুলির চেয়ে আরও প্রাসঙ্গিক।

যদি সক্রিয় করা হয়, তাহলে ভিডিও URLগুলি API সার্ভারে পাঠানো হবে এবং অন্য কোনও ডেটা পাঠানো হবে না। যদি কোনও ভিডিওতে DeArrow থাম্বনেইল না থাকে, তাহলে মূল বা স্থির ক্যাপচার দেখানো হবে
@@ -1214,6 +1224,11 @@ DeArrow সম্পর্কে আরও জানতে এখানে ট
<string name="revanced_disable_zoom_haptics_summary_on">কম্পন নিষ্ক্রিয় করা হয়েছে</string>
<string name="revanced_disable_zoom_haptics_summary_off">কম্পন সক্রিয় করা হয়েছে</string>
</patch>
<patch id="video.audio.forceOriginalAudioPatch">
<string name="revanced_force_original_audio_title">মূল অডিও বলপূর্বক চালু করুন</string>
<string name="revanced_force_original_audio_summary_on">মূল অডিও ব্যবহার করছে</string>
<string name="revanced_force_original_audio_summary_off">ডিফল্ট অডিও ব্যবহার করছে</string>
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as revanced_custom_playback_speeds_auto -->
<string name="revanced_video_quality_default_entry_1">স্বতস্ফূর্তভাবে</string>
@@ -1275,9 +1290,7 @@ DeArrow সম্পর্কে আরও জানতে এখানে ট

AVC-এর সর্বোচ্চ রেজোলিউশন 1080p, Opus অডিও কোডেক উপলব্ধ নয় এবং ভিডিও প্লেব্যাক VP9 বা AV1 এর তুলনায় আরও ইন্টারনেট ডেটা ব্যবহার করবে।"</string>
<string name="revanced_spoof_video_streams_about_ios_title">iOS স্পুফিং এর পার্শ্ব প্রতিক্রিয়া</string>
<string name="revanced_spoof_video_streams_about_ios_summary">"• ব্যক্তিগত শিশু ভিডিওগুলি প্লে নাও হতে পারে
• লাইভস্ট্রিম শুরু থেকে শুরু হয়
• ভিডিও 1 সেকেন্ড আগে শেষ হয়"</string>
<string name="revanced_spoof_video_streams_about_ios_summary">"• বেসরকারি শিশু ভিডিও চলতে নাও পারে&lt;br&gt;• ভিডিওগুলি 1 সেকেন্ড আগে শেষ হয়"</string>
<string name="revanced_spoof_video_streams_about_android_vr_title">Android VR স্পুফিং এর পার্শ্ব প্রতিক্রিয়া</string>
<string name="revanced_spoof_video_streams_about_android_vr_summary">"• শিশু ভিডিওগুলি প্লে নাও হতে পারে
• লাইভস্ট্রিম শুরু থেকে শুরু হয়
Original file line number Diff line number Diff line change
@@ -200,6 +200,8 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.zoomhaptics.zoomHapticsPatch">
</patch>
<patch id="video.audio.forceOriginalAudioPatch">
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as revanced_custom_playback_speeds_auto -->
</patch>
38 changes: 31 additions & 7 deletions patches/src/main/resources/addresources/values-ca-rES/strings.xml
Original file line number Diff line number Diff line change
@@ -33,6 +33,7 @@ Second \"item\" text"</string>
<string name="revanced_check_environment_not_near_patch_time_invalid">La data de creació de l\'APK està corrupta</string>
</patch>
<patch id="misc.settings.settingsResourcePatch">
<string name="revanced_settings_title">ReVanced</string>
<string name="revanced_settings_confirm_user_dialog_title">Vols continuar?</string>
<string name="revanced_settings_reset">Restablir</string>
<string name="revanced_settings_restart_title">Actualitza i reinicia</string>
@@ -78,6 +79,7 @@ Toca el botó Continua i permet els canvis d'optimització."</string>
<string name="revanced_settings_screen_03_feed_title">Canal</string>
<string name="revanced_settings_screen_04_player_title">Reproductor</string>
<string name="revanced_settings_screen_05_general_title">Disposició general</string>
<string name="revanced_settings_screen_06_shorts_title">Shorts</string>
<string name="revanced_settings_screen_07_seekbar_title">Barra de cerca</string>
<string name="revanced_settings_screen_08_swipe_controls_title">Controls de gestos</string>
<string name="revanced_settings_screen_11_misc_title">Misc</string>
@@ -157,9 +159,6 @@ No se t'informarà de cap esdeveniment inesperat."</string>
<string name="revanced_hide_timed_reactions_title">Amaga les reaccions temporitzades</string>
<string name="revanced_hide_timed_reactions_summary_on">S\'han amagat les reaccions temporitzades</string>
<string name="revanced_hide_timed_reactions_summary_off">Es mostren les reaccions temporitzades</string>
<string name="revanced_hide_search_result_shelf_header_title">Amaga la capçalera del prestatge de resultats de cerca</string>
<string name="revanced_hide_search_result_shelf_header_summary_on">S\'ha amagat la capçalera del prestatge</string>
<string name="revanced_hide_search_result_shelf_header_summary_off">Es mostra la capçalera del prestatge</string>
<string name="revanced_hide_channel_guidelines_title">Amaga les pautes del canal</string>
<string name="revanced_hide_channel_guidelines_summary_on">S\'han amagat les pautes del canal</string>
<string name="revanced_hide_channel_guidelines_summary_off">Es mostren les pautes del canal</string>
@@ -256,6 +255,9 @@ No se t'informarà de cap esdeveniment inesperat."</string>
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">Es mostren els vídeos relacionats</string>
<string name="revanced_comments_screen_title">Comentaris</string>
<string name="revanced_comments_screen_summary">Amaga o mostra els comentaris</string>
<string name="revanced_hide_comments_chat_summary_title">Amaga \"Resum del xat\"</string>
<string name="revanced_hide_comments_chat_summary_summary_on">El \"Resum del xat\" està amagat</string>
<string name="revanced_hide_comments_chat_summary_summary_off">Es mostra \"Resum del xat\"</string>
<string name="revanced_hide_comments_by_members_header_title">Amaga el títol \'Comentaris dels membres\'</string>
<string name="revanced_hide_comments_by_members_header_summary_on">S\'ha amagat el títol \"Comentaris dels membres\"</string>
<string name="revanced_hide_comments_by_members_header_summary_off">Es mostra el títol \"Comentaris dels membres\"</string>
@@ -464,7 +466,7 @@ Aquesta funció només està disponible per a dispositius antics"</string>
This button usually appears only on live streams. -->
<string name="revanced_hide_report_button_title">Amaga Denunciar</string>
<string name="revanced_hide_report_button_summary_on">El botó Denunciar està ocult</string>
<string name="revanced_hide_report_button_summary_off">Report button is shown</string>
<string name="revanced_hide_report_button_summary_off">Es mostra el botó d\'informe</string>
<!-- 'Remix' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_remix_button_title">Amaga Remix</string>
<string name="revanced_hide_remix_button_summary_on">El botó de Remix està amagat</string>
@@ -514,6 +516,10 @@ Nota: si actives aquesta opció, també s'amaguen els anuncis de vídeo per for
<string name="revanced_hide_navigation_button_labels_title">Amagueu les etiquetes dels botons de navegació</string>
<string name="revanced_hide_navigation_button_labels_summary_on">Les etiquetes estan amagades</string>
<string name="revanced_hide_navigation_button_labels_summary_off">Les etiquetes es mostren</string>
<string name="revanced_disable_translucent_status_bar_title">Desactiva la barra d\'estat translúcida</string>
<string name="revanced_disable_translucent_navigation_bar_light_title">Desactiva la barra translúcida de navegació clara</string>
<string name="revanced_disable_translucent_navigation_bar_light_summary_on">La barra de navegació del mode clar és opaca</string>
<string name="revanced_disable_translucent_navigation_bar_dark_summary_on">La barra de navegació del mode fosc és opaca</string>
</patch>
<patch id="layout.hide.player.flyoutmenupanel.hidePlayerFlyoutMenuPatch">
<string name="revanced_hide_player_flyout_title">Menú desplegable</string>
@@ -950,6 +956,15 @@ Ja existeix"</string>
<string name="revanced_sb_new_segment_time_start">Temps en què comença el segment</string>
<string name="revanced_sb_new_segment_time_end">Temps en què acaba el segment</string>
<string name="revanced_sb_new_segment_confirm_title">Els temps són correctes?</string>
<string name="revanced_sb_new_segment_confirm_content">"El segment és de

%1$s
a
%2$s

(%3$s)

Preparat per enviar?"</string>
<string name="revanced_sb_new_segment_start_is_before_end">L\'inici ha de ser abans del final</string>
<string name="revanced_sb_new_segment_mark_locations_first">Primer, marqueu dues ubicacions a la barra de temps</string>
<string name="revanced_sb_new_segment_preview_segment_first">Previsualitzeu el segment i assegureu-vos que s\'omet suaument</string>
@@ -1044,6 +1059,7 @@ Si després es desactiva, es recomana esborrar les dades de l'aplicació per evi
<string name="revanced_tablet_layout_user_dialog_message">Les publicacions de la comunitat no apareixen en els dissenys de tauleta</string>
</patch>
<patch id="layout.miniplayer.miniplayerPatch">
<string name="revanced_miniplayer_screen_title">Minireproductor</string>
<string name="revanced_miniplayer_screen_summary">Canvia l\'estil del reproductor minimitzat a l\'aplicació</string>
<string name="revanced_miniplayer_type_title">Tipus de \"miniplayer\"</string>
<string name="revanced_miniplayer_type_entry_0">Desactivat</string>
@@ -1126,6 +1142,7 @@ Si actives aquesta opció, es poden solucionar les imatges que falten que estan
<string name="revanced_alt_thumbnail_options_entry_2">DeArrow &amp; miniatures originals</string>
<string name="revanced_alt_thumbnail_options_entry_3">DeArrow &amp; captures estàtiques</string>
<string name="revanced_alt_thumbnail_options_entry_4">Captures estàtiques</string>
<string name="revanced_alt_thumbnail_dearrow_about_title">DeArrow</string>
<string name="revanced_alt_thumbnail_dearrow_about_summary">"DeArrow proporciona miniatures de vídeos de YouTube obtingudes de la col·laboració entre usuaris. Aquestes miniatures solen ser més rellevants que les que proporciona YouTube

Si s'activa, les URL dels vídeos s'enviaran al servidor de l'API i no s'enviarà cap més dada. Si un vídeo no té miniatures de DeArrow, es mostraran les miniatures originals o les captures de pantalla
@@ -1201,6 +1218,11 @@ Si actives aquesta opció, es poden desbloquejar qualitats de vídeo més altes"
<string name="revanced_disable_zoom_haptics_summary_on">Els hàptics estan desactivats</string>
<string name="revanced_disable_zoom_haptics_summary_off">Els hàptics estan habilitats</string>
</patch>
<patch id="video.audio.forceOriginalAudioPatch">
<string name="revanced_force_original_audio_title">Forçar àudio original</string>
<string name="revanced_force_original_audio_summary_on">Utilitzant àudio original</string>
<string name="revanced_force_original_audio_summary_off">Utilitzant àudio predeterminat</string>
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as revanced_custom_playback_speeds_auto -->
<string name="revanced_video_quality_default_entry_1">Automàtic</string>
@@ -1210,6 +1232,7 @@ Si actives aquesta opció, es poden desbloquejar qualitats de vídeo més altes"
<string name="revanced_video_quality_default_wifi_title">Qualitat de vídeo predeterminada a la xarxa Wi-Fi</string>
<string name="revanced_video_quality_default_mobile_title">Qualitat de vídeo predeterminada a la xarxa mòbil</string>
<string name="revanced_remember_video_quality_mobile">mòbil</string>
<string name="revanced_remember_video_quality_wifi">wifi</string>
<string name="revanced_remember_video_quality_toast">S\'ha canviat la qualitat predeterminada de %1$s a: %2$s</string>
</patch>
<patch id="video.speed.button.playbackSpeedButtonPatch">
@@ -1261,9 +1284,8 @@ La reproducció de vídeo pot no funcionar"</string>

AVC té una resolució màxima de 1080p, el còdec d'àudio Opus no està disponible i la reproducció de vídeo utilitzarà més dades d'Internet que VP9 o AV1."</string>
<string name="revanced_spoof_video_streams_about_ios_title">Efectes secundaris de la falsificació d\'iOS</string>
<string name="revanced_spoof_video_streams_about_ios_summary">"• Els vídeos privats de nens poden no reproduir-se
• Les emissions en directe comencen des del principi
• Els vídeos acaben 1 segon abans"</string>
<string name="revanced_spoof_video_streams_about_ios_summary">"• Els vídeos privats per a nens potser no es reprodueixen
• Els vídeos finalitzen 1 segon abans"</string>
<string name="revanced_spoof_video_streams_about_android_vr_title">Efecte secundaris de la suplantació d\'Android VR</string>
<string name="revanced_spoof_video_streams_about_android_vr_summary">"• Els vídeos de nens poden no reproduir-se
• Les emissions en directe comencen des del principi
@@ -1335,6 +1357,8 @@ AVC té una resolució màxima de 1080p, el còdec d'àudio Opus no està dispon
<string name="revanced_embedded_ads_service_failed">%s ha retornat un error, és possible que es mostrin anuncis. Prova de canviar el servei de bloqueig d\'anuncis a la configuració.</string>
<string name="revanced_block_embedded_ads_title">Bloquejar anuncis de vídeo integrats</string>
<string name="revanced_block_embedded_ads_entry_1">Desactivat</string>
<string name="revanced_block_embedded_ads_entry_2">Proxy lluminoso</string>
<string name="revanced_block_embedded_ads_entry_3">Proxy PurpleAdBlock</string>
</patch>
<patch id="ad.video.videoAdsPatch">
<string name="revanced_block_video_ads_title">Bloquejar anuncis de vídeo</string>
27 changes: 18 additions & 9 deletions patches/src/main/resources/addresources/values-cs-rCZ/strings.xml
Original file line number Diff line number Diff line change
@@ -33,6 +33,7 @@ Second \"item\" text"</string>
<string name="revanced_check_environment_not_near_patch_time_invalid">Datum sestavení souboru APK je poškozeno</string>
</patch>
<patch id="misc.settings.settingsResourcePatch">
<string name="revanced_settings_title">ReVanced</string>
<string name="revanced_settings_confirm_user_dialog_title">Přejete si pokračovat?</string>
<string name="revanced_settings_reset">Výchozí</string>
<string name="revanced_settings_restart_title">Obnovit a restartovat</string>
@@ -42,7 +43,7 @@ Second \"item\" text"</string>
<string name="revanced_settings_import_reset">Nastavení ReVanced obnoveno do výchozího stavu</string>
<string name="revanced_settings_import_success">Importováno %d nastavení</string>
<string name="revanced_settings_import_failure_parse">Importováni selhalo: %s</string>
<string name="revanced_pref_import_export_title">Import / Export</string>
<string name="revanced_pref_import_export_title">Importovat / Exportovat</string>
<string name="revanced_pref_import_export_summary">Importovat/exportovat nastavení ReVanced</string>
<!-- Settings about dialog. -->
<string name="revanced_settings_about_links_body">Používáte verzi ReVanced Patches &lt;i&gt;%s&lt;/i&gt;</string>
@@ -78,6 +79,7 @@ Klepněte na tlačítko Pokračovat a povolte změny optimalizace."</string>
<string name="revanced_settings_screen_03_feed_title">Přísun</string>
<string name="revanced_settings_screen_04_player_title">Přehrávač</string>
<string name="revanced_settings_screen_05_general_title">Celkové rozložení</string>
<string name="revanced_settings_screen_06_shorts_title">Shorts</string>
<string name="revanced_settings_screen_07_seekbar_title">Lišta</string>
<string name="revanced_settings_screen_08_swipe_controls_title">Ovládání gesty</string>
<string name="revanced_settings_screen_11_misc_title">Ostatní</string>
@@ -151,15 +153,12 @@ Nebudete informováni o žádné neočekávané události."</string>
<string name="revanced_hide_search_result_recommendations_summary_off">Odporúčania sú zobrazené</string>
<!-- 'Show more' should be translated with the same localized wording that YouTube displays.
This button usually appears when searching for a YT creator. -->
<string name="revanced_hide_show_more_button_title">Hide \'Show more\' button</string>
<string name="revanced_hide_show_more_button_title">Skrýt tlačítko „Zobrazit více“</string>
<string name="revanced_hide_show_more_button_summary_on">Tlačítko je skryto</string>
<string name="revanced_hide_show_more_button_summary_off">Tlačítko je zobrazeno</string>
<string name="revanced_hide_timed_reactions_title">Skrýt reakce zobrazené po čase</string>
<string name="revanced_hide_timed_reactions_summary_on">Reakce zobrazené po čase jsou skryty</string>
<string name="revanced_hide_timed_reactions_summary_off">Reakce se zobrazují po čase</string>
<string name="revanced_hide_search_result_shelf_header_title">Skrýt hlavičku poličky s výsledky vyhledávání</string>
<string name="revanced_hide_search_result_shelf_header_summary_on">Hlavička poličky s výsledky vyhledávání je skryta</string>
<string name="revanced_hide_search_result_shelf_header_summary_off">Hlavička poličky s výsledky vyhledávání se zobrazuje</string>
<string name="revanced_hide_channel_guidelines_title">Skrýt pravidla kanálu</string>
<string name="revanced_hide_channel_guidelines_summary_on">Pokyny kanálu sa nezobrazujú</string>
<string name="revanced_hide_channel_guidelines_summary_off">Zobrazujú sa pokyny kanálu</string>
@@ -438,7 +437,7 @@ Tato funkce je dostupná pouze pro starší zařízení"</string>
<string name="revanced_swipe_lowest_value_enable_auto_brightness_title">Povolit gesto pro automatický jas</string>
<string name="revanced_swipe_lowest_value_enable_auto_brightness_summary_on">Přejetím dolů na nejnižší hodnotu gesta pro jas aktivujete automatický jas</string>
<string name="revanced_swipe_lowest_value_enable_auto_brightness_summary_off">Přejetím dolů na nejnižší hodnotu neaktivujete automatický jas</string>
<string name="revanced_swipe_lowest_value_enable_auto_brightness_overlay_text">Auto</string>
<string name="revanced_swipe_lowest_value_enable_auto_brightness_overlay_text">Automat</string>
<string name="revanced_swipe_overlay_timeout_title">Timeout překrytí gesta</string>
<string name="revanced_swipe_overlay_timeout_summary">Doba v milisekundách, po kterou je překrytí viditelné</string>
<string name="revanced_swipe_text_overlay_size_title">Velikost textu překrytí gesta</string>
@@ -517,6 +516,10 @@ Poznámka: Povolení této funkce také vynuceně skryje video reklamy"</string>
<string name="revanced_hide_navigation_button_labels_title">Skrýt štítky navigačních tlačítek</string>
<string name="revanced_hide_navigation_button_labels_summary_on">Štítky jsou skryty</string>
<string name="revanced_hide_navigation_button_labels_summary_off">Štítky jsou zobrazeny</string>
<string name="revanced_disable_translucent_status_bar_title">Deaktivovat průsvitný stavový řádek</string>
<string name="revanced_disable_translucent_navigation_bar_light_title">Deaktivovat světlý průsvitný navigační panel</string>
<string name="revanced_disable_translucent_navigation_bar_light_summary_on">Navigační panel v světlém režimu je neprůhledný</string>
<string name="revanced_disable_translucent_navigation_bar_dark_summary_on">Navigační panel v tmavém režimu je neprůhledný</string>
</patch>
<patch id="layout.hide.player.flyoutmenupanel.hidePlayerFlyoutMenuPatch">
<string name="revanced_hide_player_flyout_title">Menu vyskakovacích oken</string>
@@ -1056,6 +1059,7 @@ Pokud bude později vypnuta, doporučujeme vymazat data aplikace, aby se zabrán
<string name="revanced_tablet_layout_user_dialog_message">Příspěvky komunity se v rozvržení tabletu nezobrazují</string>
</patch>
<patch id="layout.miniplayer.miniplayerPatch">
<string name="revanced_miniplayer_screen_title">Mini přehrávač</string>
<string name="revanced_miniplayer_screen_summary">Změnit styl minimalizovaného přehrávače v aplikaci</string>
<string name="revanced_miniplayer_type_title">Typ přehrávače</string>
<string name="revanced_miniplayer_type_entry_0">Vypnuto</string>
@@ -1213,6 +1217,11 @@ Povolením této funkce lze odemknout vyšší kvality videa"</string>
<string name="revanced_disable_zoom_haptics_summary_on">Haptika je zakázána</string>
<string name="revanced_disable_zoom_haptics_summary_off">Haptika je povolena</string>
</patch>
<patch id="video.audio.forceOriginalAudioPatch">
<string name="revanced_force_original_audio_title">Vynutit původní zvuk</string>
<string name="revanced_force_original_audio_summary_on">Používání původního zvuku</string>
<string name="revanced_force_original_audio_summary_off">Používání výchozího zvuku</string>
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as revanced_custom_playback_speeds_auto -->
<string name="revanced_video_quality_default_entry_1">Automaticky</string>
@@ -1222,6 +1231,7 @@ Povolením této funkce lze odemknout vyšší kvality videa"</string>
<string name="revanced_video_quality_default_wifi_title">Výchozí kvalita videa v síti Wi-Fi</string>
<string name="revanced_video_quality_default_mobile_title">Výchozí kvalita videa v mobilní síti</string>
<string name="revanced_remember_video_quality_mobile">mobilní</string>
<string name="revanced_remember_video_quality_wifi">Wi-Fi</string>
<string name="revanced_remember_video_quality_toast">Výchozí kvalita %1$s změněna na: %2$s</string>
</patch>
<patch id="video.speed.button.playbackSpeedButtonPatch">
@@ -1273,9 +1283,6 @@ Přehrávání videa nemusí fungovat"</string>

AVC má maximální rozlišení 1080p, audio kodek Opus není dostupný a přehrávání videa bude používat více internetových dat než VP9 nebo AV1."</string>
<string name="revanced_spoof_video_streams_about_ios_title">Vedlejší účinky napodobování iOS</string>
<string name="revanced_spoof_video_streams_about_ios_summary">"• Soukromá videa pro děti se nemusí přehrát
• Livestreamy začínají od začátku
• Videa končí o 1 sekundu dříve"</string>
<string name="revanced_spoof_video_streams_about_android_vr_title">Vedlejší účinky napodobování Android VR</string>
<string name="revanced_spoof_video_streams_about_android_vr_summary">"• Videa pro děti se nemusí přehrát
• Livestreamy začínají od začátku
@@ -1347,6 +1354,8 @@ AVC má maximální rozlišení 1080p, audio kodek Opus není dostupný a přehr
<string name="revanced_embedded_ads_service_failed">%s vrátil chybu, reklamy se mohou zobrazit. Zkuste změnit službu blokování reklam v nastavení.</string>
<string name="revanced_block_embedded_ads_title">Blokovat vložené video reklamy</string>
<string name="revanced_block_embedded_ads_entry_1">Vypnuto</string>
<string name="revanced_block_embedded_ads_entry_2">Proxy Luminous</string>
<string name="revanced_block_embedded_ads_entry_3">Proxy PurpleAdBlock</string>
</patch>
<patch id="ad.video.videoAdsPatch">
<string name="revanced_block_video_ads_title">Blokovat video reklamy</string>
Loading

0 comments on commit ccea384

Please sign in to comment.