mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-26 02:44:08 +01:00
Compare commits
49 Commits
v5.5.2-dev
...
v5.7.2-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55d01c92d1 | ||
|
|
ca21a69550 | ||
|
|
634d0b4058 | ||
|
|
47ea8d5ec8 | ||
|
|
9509ed53f3 | ||
|
|
39542ddf55 | ||
|
|
e1741130af | ||
|
|
e54eb3ce87 | ||
|
|
0ae756b0fc | ||
|
|
77a0ac5c9c | ||
|
|
899121b9de | ||
|
|
838edb48e7 | ||
|
|
b2665c916a | ||
|
|
4b81f7009b | ||
|
|
1a4c39a2ee | ||
|
|
99334d1e53 | ||
|
|
2850a6ed4e | ||
|
|
f28eb5105b | ||
|
|
69bed4d9fa | ||
|
|
a5f1efac27 | ||
|
|
b51be82cff | ||
|
|
b8635d0b88 | ||
|
|
78699c8bbf | ||
|
|
aeedec7fed | ||
|
|
32b614696b | ||
|
|
a0b63dfa23 | ||
|
|
f0f53cf72f | ||
|
|
cdb68209d1 | ||
|
|
7369f7b8d5 | ||
|
|
db521b940b | ||
|
|
25d7cc68ae | ||
|
|
9495064e6e | ||
|
|
64864c2cdb | ||
|
|
ad0ffb3328 | ||
|
|
06800324aa | ||
|
|
ec746cb05a | ||
|
|
67c5530ea6 | ||
|
|
cd08717783 | ||
|
|
7bac023ea5 | ||
|
|
1d0ec98bec | ||
|
|
3c603fac2d | ||
|
|
20a7ad4715 | ||
|
|
25a60e305e | ||
|
|
c7f42d9a3c | ||
|
|
670f100a29 | ||
|
|
19140e5918 | ||
|
|
1dde485013 | ||
|
|
5efcdd31c8 | ||
|
|
e6529837cb |
2
.github/workflows/pull_strings.yml
vendored
2
.github/workflows/pull_strings.yml
vendored
@@ -23,6 +23,7 @@ jobs:
|
||||
uses: crowdin/github-action@v2
|
||||
with:
|
||||
config: crowdin.yml
|
||||
upload_sources: false
|
||||
download_translations: true
|
||||
localization_branch_name: feat/translations
|
||||
create_pull_request: false
|
||||
@@ -39,4 +40,3 @@ jobs:
|
||||
destination_branch: dev
|
||||
pr_title: "chore: Sync translations"
|
||||
pr_body: "Sync translations from [crowdin.com/project/revanced](https://crowdin.com/project/revanced)"
|
||||
pr_draft: true
|
||||
|
||||
164
CHANGELOG.md
164
CHANGELOG.md
@@ -1,3 +1,167 @@
|
||||
## [5.7.2-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.7.1...v5.7.2-dev.1) (2024-12-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Add iOS TV client, restore iOS 'force AVC', show client type in stats for nerds ([#4202](https://github.com/ReVanced/revanced-patches/issues/4202)) ([ab29f80](https://github.com/ReVanced/revanced-patches/commit/ab29f808a9f55b5ab0055533c1a6de549b0631a6))
|
||||
|
||||
## [5.7.1](https://github.com/ReVanced/revanced-patches/compare/v5.7.0...v5.7.1) (2024-12-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - SponsorBlock:** Show a toast and not a dialog if segment submitted successfully ([134b189](https://github.com/ReVanced/revanced-patches/commit/134b189791113dcf1a1cb7c87b8a0954f432730c))
|
||||
* **YouTube - Spoof video streams:** Use 2 letter device language code ([33ff997](https://github.com/ReVanced/revanced-patches/commit/33ff9972000581aca92262f984efb114eeeb9537))
|
||||
* **YouTube - Spoof video streams:** Use Android VR authentication if using default audio language ([#4191](https://github.com/ReVanced/revanced-patches/issues/4191)) ([98773cc](https://github.com/ReVanced/revanced-patches/commit/98773cc7d46e5c9c7715b82c8006f1ccbcc5443c))
|
||||
* **YouTube - Theme:** Use dark theme color for status and navigation bar ([0240efe](https://github.com/ReVanced/revanced-patches/commit/0240efe33e5444625ca2b760c861c9046d3dc836))
|
||||
* **YouTube:** Do not reset playback speed to 1.0x after closing comment thread (Fixes stock YouTube bug) ([#4195](https://github.com/ReVanced/revanced-patches/issues/4195)) ([dda788c](https://github.com/ReVanced/revanced-patches/commit/dda788c58c789d4f91646ea8e8a8077f590ab6b3))
|
||||
|
||||
## [5.7.1-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.7.1-dev.4...v5.7.1-dev.5) (2024-12-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Use 2 letter device language code ([33ff997](https://github.com/ReVanced/revanced-patches/commit/33ff9972000581aca92262f984efb114eeeb9537))
|
||||
|
||||
## [5.7.1-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.7.1-dev.3...v5.7.1-dev.4) (2024-12-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Do not reset playback speed to 1.0x after closing comment thread (Fixes stock YouTube bug) ([#4195](https://github.com/ReVanced/revanced-patches/issues/4195)) ([dda788c](https://github.com/ReVanced/revanced-patches/commit/dda788c58c789d4f91646ea8e8a8077f590ab6b3))
|
||||
|
||||
## [5.7.1-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.7.1-dev.2...v5.7.1-dev.3) (2024-12-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - SponsorBlock:** Show a toast and not a dialog if segment submitted successfully ([134b189](https://github.com/ReVanced/revanced-patches/commit/134b189791113dcf1a1cb7c87b8a0954f432730c))
|
||||
|
||||
## [5.7.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.7.1-dev.1...v5.7.1-dev.2) (2024-12-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Theme:** Use dark theme color for status and navigation bar ([0240efe](https://github.com/ReVanced/revanced-patches/commit/0240efe33e5444625ca2b760c861c9046d3dc836))
|
||||
|
||||
## [5.7.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.7.0...v5.7.1-dev.1) (2024-12-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Use Android VR authentication if using default audio language ([#4191](https://github.com/ReVanced/revanced-patches/issues/4191)) ([98773cc](https://github.com/ReVanced/revanced-patches/commit/98773cc7d46e5c9c7715b82c8006f1ccbcc5443c))
|
||||
|
||||
# [5.7.0](https://github.com/ReVanced/revanced-patches/compare/v5.6.0...v5.7.0) (2024-12-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Force original audio:** Use correct availability for settings UI ([a7eedcb](https://github.com/ReVanced/revanced-patches/commit/a7eedcb4cca6b7b12629c478c24c0899c80e3615))
|
||||
* **YouTube - Spoof video stream:** Remove UI client type setting. Allow setting default audio language. ([#4184](https://github.com/ReVanced/revanced-patches/issues/4184)) ([99f3f29](https://github.com/ReVanced/revanced-patches/commit/99f3f29c649bf7693c05bbce2bb49bd53e05f050))
|
||||
* **YouTube - Spoof video streams:** Remove iOS, add clients Android TV and Android Creator ([#4180](https://github.com/ReVanced/revanced-patches/issues/4180)) ([86abfb2](https://github.com/ReVanced/revanced-patches/commit/86abfb2b0d4675f0a1cb9ab244783075bfe89281))
|
||||
* **YouTube:** Change fingerprints to support a wider range of target versions ([8a09174](https://github.com/ReVanced/revanced-patches/commit/8a09174def205a26ce49cb7815097e235069526a))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Support version `19.47.53` ([#4182](https://github.com/ReVanced/revanced-patches/issues/4182)) ([2089e61](https://github.com/ReVanced/revanced-patches/commit/2089e613d36c45352db7d852aaee0087b1c3e1a4))
|
||||
|
||||
# [5.7.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.6.1-dev.4...v5.7.0-dev.1) (2024-12-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Support version `19.47.53` ([#4182](https://github.com/ReVanced/revanced-patches/issues/4182)) ([2089e61](https://github.com/ReVanced/revanced-patches/commit/2089e613d36c45352db7d852aaee0087b1c3e1a4))
|
||||
|
||||
## [5.6.1-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.6.1-dev.3...v5.6.1-dev.4) (2024-12-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video stream:** Remove UI client type setting. Allow setting default audio language. ([#4184](https://github.com/ReVanced/revanced-patches/issues/4184)) ([99f3f29](https://github.com/ReVanced/revanced-patches/commit/99f3f29c649bf7693c05bbce2bb49bd53e05f050))
|
||||
|
||||
## [5.6.1-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.6.1-dev.2...v5.6.1-dev.3) (2024-12-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Force original audio:** Use correct availability for settings UI ([a7eedcb](https://github.com/ReVanced/revanced-patches/commit/a7eedcb4cca6b7b12629c478c24c0899c80e3615))
|
||||
|
||||
## [5.6.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.6.1-dev.1...v5.6.1-dev.2) (2024-12-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Remove iOS, add clients Android TV and Android Creator ([#4180](https://github.com/ReVanced/revanced-patches/issues/4180)) ([86abfb2](https://github.com/ReVanced/revanced-patches/commit/86abfb2b0d4675f0a1cb9ab244783075bfe89281))
|
||||
|
||||
## [5.6.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.6.0...v5.6.1-dev.1) (2024-12-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Change fingerprints to support a wider range of target versions ([8a09174](https://github.com/ReVanced/revanced-patches/commit/8a09174def205a26ce49cb7815097e235069526a))
|
||||
|
||||
# [5.6.0](https://github.com/ReVanced/revanced-patches/compare/v5.5.1...v5.6.0) (2024-12-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Twitter - Change link sharing domain:** Use correct extension package ([ad7fab6](https://github.com/ReVanced/revanced-patches/commit/ad7fab67319ba23f267d27da9b74266965fc4be3))
|
||||
* **YouTube - Force original audio:** Use correct original audio stream if app language is not English ([0d20171](https://github.com/ReVanced/revanced-patches/commit/0d2017133efac230887b5c2a331d87159df8af11))
|
||||
* **YouTube - Hide layout components:** Hide new kind of community post ([#4155](https://github.com/ReVanced/revanced-patches/issues/4155)) ([08f68cb](https://github.com/ReVanced/revanced-patches/commit/08f68cb5d33f2cfe656d2f93d159c69981f31418))
|
||||
* **YouTube - Miniplayer:** Use estimated maximum on screen size for devices with low density screens ([#4150](https://github.com/ReVanced/revanced-patches/issues/4150)) ([2694158](https://github.com/ReVanced/revanced-patches/commit/2694158c3c9935ede21c96832533222f850068df))
|
||||
* **YouTube - Open Shorts in regular player:** Do not show the miniplayer after opening a Short while a video is playing ([894e366](https://github.com/ReVanced/revanced-patches/commit/894e36665d17d5a3a5728961d424dffc55faa50b))
|
||||
* **YouTube - SponsorBlock:** Show create new segment error messages using a dialog ([#4148](https://github.com/ReVanced/revanced-patches/issues/4148)) ([5870906](https://github.com/ReVanced/revanced-patches/commit/587090636dfff0b358b15026cf7d47c65a4296dc))
|
||||
* **YouTube - Spoof video streams:** Change default spoofing to iOS, allow setting a default language with Android VR ([#4171](https://github.com/ReVanced/revanced-patches/issues/4171)) ([171b4e7](https://github.com/ReVanced/revanced-patches/commit/171b4e7e40066e38fba773b7a6525e9a038779ef))
|
||||
* **YouTube - Spoof video streams:** Update iOS client version ([df3aeed](https://github.com/ReVanced/revanced-patches/commit/df3aeed3b173e408fad80197a89ec5d003a2b328))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Add `Open Shorts in regular player` patch ([#4153](https://github.com/ReVanced/revanced-patches/issues/4153)) ([c7c5e5b](https://github.com/ReVanced/revanced-patches/commit/c7c5e5b2b9cf63d8225bb6bd5e735ddf945b6c29))
|
||||
|
||||
# [5.6.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.6.0-dev.5...v5.6.0-dev.6) (2024-12-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Update iOS client version ([df3aeed](https://github.com/ReVanced/revanced-patches/commit/df3aeed3b173e408fad80197a89ec5d003a2b328))
|
||||
|
||||
# [5.6.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.6.0-dev.4...v5.6.0-dev.5) (2024-12-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Change default spoofing to iOS, allow setting a default language with Android VR ([#4171](https://github.com/ReVanced/revanced-patches/issues/4171)) ([171b4e7](https://github.com/ReVanced/revanced-patches/commit/171b4e7e40066e38fba773b7a6525e9a038779ef))
|
||||
|
||||
# [5.6.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.6.0-dev.3...v5.6.0-dev.4) (2024-12-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Force original audio:** Use correct original audio stream if app language is not English ([0d20171](https://github.com/ReVanced/revanced-patches/commit/0d2017133efac230887b5c2a331d87159df8af11))
|
||||
|
||||
# [5.6.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.6.0-dev.2...v5.6.0-dev.3) (2024-12-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Twitter - Change link sharing domain:** Use correct extension package ([ad7fab6](https://github.com/ReVanced/revanced-patches/commit/ad7fab67319ba23f267d27da9b74266965fc4be3))
|
||||
|
||||
# [5.6.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.6.0-dev.1...v5.6.0-dev.2) (2024-12-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Open Shorts in regular player:** Do not show the miniplayer after opening a Short while a video is playing ([894e366](https://github.com/ReVanced/revanced-patches/commit/894e36665d17d5a3a5728961d424dffc55faa50b))
|
||||
|
||||
# [5.6.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.5.2-dev.2...v5.6.0-dev.1) (2024-12-19)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Add `Open Shorts in regular player` patch ([#4153](https://github.com/ReVanced/revanced-patches/issues/4153)) ([c7c5e5b](https://github.com/ReVanced/revanced-patches/commit/c7c5e5b2b9cf63d8225bb6bd5e735ddf945b6c29))
|
||||
|
||||
## [5.5.2-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.5.2-dev.1...v5.5.2-dev.2) (2024-12-17)
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package app.revanced.extension.shared.settings;
|
||||
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.AudioStreamLanguageOverrideAvailability;
|
||||
import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.SpoofiOSAvailability;
|
||||
|
||||
import app.revanced.extension.shared.spoof.AudioStreamLanguage;
|
||||
@@ -22,9 +23,11 @@ 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, new SpoofiOSAvailability());
|
||||
public static final EnumSetting<AudioStreamLanguage> SPOOF_VIDEO_STREAMS_LANGUAGE = new EnumSetting<>("revanced_spoof_video_streams_language", AudioStreamLanguage.DEFAULT, new AudioStreamLanguageOverrideAvailability());
|
||||
public static final BooleanSetting SPOOF_STREAMING_DATA_STATS_FOR_NERDS = new BooleanSetting("revanced_spoof_streaming_data_stats_for_nerds", TRUE);
|
||||
public static final BooleanSetting SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC = new BooleanSetting("revanced_spoof_video_streams_ios_force_avc", FALSE, true,
|
||||
"revanced_spoof_video_streams_ios_force_avc_user_dialog_message", new 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));
|
||||
// Client type must be last spoof setting due to cyclic references.
|
||||
public static final EnumSetting<ClientType> SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client_type", ClientType.ANDROID_VR, true, parent(SPOOF_VIDEO_STREAMS));
|
||||
|
||||
}
|
||||
|
||||
@@ -4,14 +4,12 @@ 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.
|
||||
* The current app language.
|
||||
*/
|
||||
DEFAULT,
|
||||
|
||||
// Language codes found in locale_config.xml
|
||||
// Region specific variants of Chinese/English/Spanish/French have been removed.
|
||||
// All region specific variants have been removed.
|
||||
AF,
|
||||
AM,
|
||||
AR,
|
||||
@@ -65,8 +63,7 @@ public enum AudioStreamLanguage {
|
||||
OR,
|
||||
PA,
|
||||
PL,
|
||||
PT_BR,
|
||||
PT_PT,
|
||||
PT,
|
||||
RO,
|
||||
RU,
|
||||
SI,
|
||||
@@ -88,26 +85,22 @@ public enum AudioStreamLanguage {
|
||||
ZH,
|
||||
ZU;
|
||||
|
||||
private final String iso639_1;
|
||||
private final String language;
|
||||
|
||||
AudioStreamLanguage() {
|
||||
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);
|
||||
}
|
||||
language = name().toLowerCase(Locale.US);
|
||||
}
|
||||
|
||||
public String getIso639_1() {
|
||||
/**
|
||||
* @return The 2 letter ISO 639_1 language code.
|
||||
*/
|
||||
public String getLanguage() {
|
||||
// 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) {
|
||||
return Locale.getDefault().toLanguageTag();
|
||||
return Locale.getDefault().getLanguage();
|
||||
}
|
||||
|
||||
return iso639_1;
|
||||
return language;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,40 +7,64 @@ import androidx.annotation.Nullable;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
|
||||
public enum ClientType {
|
||||
// Specific purpose for age restricted, or private videos, because the iOS client is not logged in.
|
||||
// https://dumps.tadiphone.dev/dumps/oculus/eureka
|
||||
ANDROID_VR(28,
|
||||
ANDROID_VR_NO_AUTH(
|
||||
28,
|
||||
"ANDROID_VR",
|
||||
"Quest 3",
|
||||
"12",
|
||||
"com.google.android.apps.youtube.vr.oculus/1.56.21 (Linux; U; Android 12; GB) gzip",
|
||||
"32", // Android 12.1
|
||||
"1.56.21",
|
||||
false,
|
||||
"Android VR No auth"
|
||||
),
|
||||
ANDROID_UNPLUGGED(
|
||||
29,
|
||||
"ANDROID_UNPLUGGED",
|
||||
"Google TV Streamer",
|
||||
"14",
|
||||
"com.google.android.apps.youtube.unplugged/8.49.0 (Linux; U; Android 14; GB) gzip",
|
||||
"34",
|
||||
"8.49.0",
|
||||
true,
|
||||
false),
|
||||
// Specific for kids videos.
|
||||
IOS(5,
|
||||
"IOS",
|
||||
"Android TV"
|
||||
),
|
||||
ANDROID_VR(
|
||||
ANDROID_VR_NO_AUTH.id,
|
||||
ANDROID_VR_NO_AUTH.clientName,
|
||||
ANDROID_VR_NO_AUTH.deviceModel,
|
||||
ANDROID_VR_NO_AUTH.osVersion,
|
||||
ANDROID_VR_NO_AUTH.userAgent,
|
||||
ANDROID_VR_NO_AUTH.androidSdkVersion,
|
||||
ANDROID_VR_NO_AUTH.clientVersion,
|
||||
true,
|
||||
"Android VR"
|
||||
),
|
||||
IOS_UNPLUGGED(33,
|
||||
"IOS_UNPLUGGED",
|
||||
forceAVC()
|
||||
? "iPhone12,5" // 11 Pro Max (last device with iOS 13)
|
||||
: "iPhone16,2", // 15 Pro Max
|
||||
// iOS 13 and earlier uses only AVC. 14+ adds VP9 and AV1.
|
||||
// iOS 13 and earlier uses only AVC. 14+ adds VP9 and AV1.
|
||||
forceAVC()
|
||||
? "13.7.17H35" // Last release of iOS 13.
|
||||
: "17.5.1.21F90",
|
||||
: "18.1.1.22B91",
|
||||
forceAVC()
|
||||
? "com.google.ios.youtube/17.40.5 (iPhone; U; CPU iOS 13_7 like Mac OS X)"
|
||||
: "com.google.ios.youtube/19.47.7 (iPhone; U; CPU iOS 17_5_1 like Mac OS X)",
|
||||
? "com.google.ios.youtubeunplugged/6.45 (iPhone; U; CPU iOS 13_7 like Mac OS X)"
|
||||
: "com.google.ios.youtubeunplugged/8.33 (iPhone; U; CPU iOS 18_1_1 like Mac OS X)",
|
||||
null,
|
||||
// Version number should be a valid iOS release.
|
||||
// https://www.ipa4fun.com/history/185230
|
||||
// https://www.ipa4fun.com/history/152043/
|
||||
// Some newer versions can also force AVC,
|
||||
// but 6.45 is the last version that supports iOS 13.
|
||||
forceAVC()
|
||||
// Some newer versions can also force AVC,
|
||||
// but 17.40 is the last version that supports iOS 13.
|
||||
? "17.40.5"
|
||||
: "19.47.7",
|
||||
false,
|
||||
true
|
||||
? "6.45"
|
||||
: "8.33",
|
||||
true,
|
||||
forceAVC()
|
||||
? "iOS TV Force AVC"
|
||||
: "iOS TV"
|
||||
);
|
||||
|
||||
private static boolean forceAVC() {
|
||||
@@ -88,9 +112,9 @@ public enum ClientType {
|
||||
public final boolean canLogin;
|
||||
|
||||
/**
|
||||
* If a language code should be used.
|
||||
* Friendly name displayed in stats for nerds.
|
||||
*/
|
||||
public final boolean useLanguageCode;
|
||||
public final String friendlyName;
|
||||
|
||||
ClientType(int id,
|
||||
String clientName,
|
||||
@@ -100,7 +124,7 @@ public enum ClientType {
|
||||
@Nullable String androidSdkVersion,
|
||||
String clientVersion,
|
||||
boolean canLogin,
|
||||
boolean useLanguageCode) {
|
||||
String friendlyName) {
|
||||
this.id = id;
|
||||
this.clientName = clientName;
|
||||
this.deviceModel = deviceModel;
|
||||
@@ -109,6 +133,7 @@ public enum ClientType {
|
||||
this.androidSdkVersion = androidSdkVersion;
|
||||
this.clientVersion = clientVersion;
|
||||
this.canLogin = canLogin;
|
||||
this.useLanguageCode = useLanguageCode;
|
||||
this.friendlyName = friendlyName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.revanced.extension.shared.spoof;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
@@ -18,7 +19,7 @@ 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;
|
||||
&& BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS_UNPLUGGED;
|
||||
|
||||
/**
|
||||
* Any unreachable ip address. Used to intentionally fail requests.
|
||||
@@ -26,6 +27,13 @@ public class SpoofVideoStreamsPatch {
|
||||
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);
|
||||
|
||||
/**
|
||||
* @return If this patch was included during patching.
|
||||
*/
|
||||
private static boolean isPatchIncluded() {
|
||||
return false; // Modified during patching.
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* Blocks /get_watch requests by returning an unreachable URI.
|
||||
@@ -82,6 +90,17 @@ public class SpoofVideoStreamsPatch {
|
||||
return SPOOF_STREAMING_DATA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* Only invoked when playing a livestream on an iOS client.
|
||||
*/
|
||||
public static boolean fixHLSCurrentTime(boolean original) {
|
||||
if (!SPOOF_STREAMING_DATA) {
|
||||
return original;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
@@ -171,22 +190,47 @@ public class SpoofVideoStreamsPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*
|
||||
* Fixes iOS livestreams starting from the beginning.
|
||||
*/
|
||||
public static boolean fixHLSCurrentTime(boolean original) {
|
||||
if (FIX_HLS_CURRENT_TIME) {
|
||||
return false;
|
||||
public static String appendSpoofedClient(String videoFormat) {
|
||||
try {
|
||||
if (SPOOF_STREAMING_DATA && BaseSettings.SPOOF_STREAMING_DATA_STATS_FOR_NERDS.get()
|
||||
&& !TextUtils.isEmpty(videoFormat)) {
|
||||
// Force LTR layout, to match the same LTR video time/length layout YouTube uses for all languages.
|
||||
return "\u202D" + videoFormat + "\u2009(" // u202D = left to right override
|
||||
+ StreamingDataRequest.getLastSpoofedClientName() + ")";
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "appendSpoofedClient failure", ex);
|
||||
}
|
||||
|
||||
return original;
|
||||
return videoFormat;
|
||||
}
|
||||
|
||||
public static final class NotSpoofingAndroidAvailability implements Setting.Availability {
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (SpoofVideoStreamsPatch.isPatchIncluded()) {
|
||||
return !BaseSettings.SPOOF_VIDEO_STREAMS.get()
|
||||
|| BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS_UNPLUGGED;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class AudioStreamLanguageOverrideAvailability implements Setting.Availability {
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return !BaseSettings.SPOOF_VIDEO_STREAMS.get()
|
||||
|| BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.ANDROID_VR_NO_AUTH;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
&& BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS_UNPLUGGED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.requests.Requester;
|
||||
import app.revanced.extension.shared.requests.Route;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.shared.spoof.AudioStreamLanguage;
|
||||
import app.revanced.extension.shared.spoof.ClientType;
|
||||
|
||||
final class PlayerRoutes {
|
||||
@@ -36,10 +37,17 @@ final class PlayerRoutes {
|
||||
try {
|
||||
JSONObject context = new JSONObject();
|
||||
|
||||
// Can override default language only if no login is used.
|
||||
// Could use preferred audio for all clients that do not login,
|
||||
// but if this is a fall over client it will set the language even though
|
||||
// the audio language is not selectable in the UI.
|
||||
ClientType userSelectedClient = BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get();
|
||||
AudioStreamLanguage language = userSelectedClient == ClientType.ANDROID_VR_NO_AUTH
|
||||
? BaseSettings.SPOOF_VIDEO_STREAMS_LANGUAGE.get()
|
||||
: AudioStreamLanguage.DEFAULT;
|
||||
|
||||
JSONObject client = new JSONObject();
|
||||
if (clientType.useLanguageCode) {
|
||||
client.put("hl", BaseSettings.SPOOF_VIDEO_STREAMS_LANGUAGE.get().getIso639_1());
|
||||
}
|
||||
client.put("hl", language.getLanguage());
|
||||
client.put("clientName", clientType.clientName);
|
||||
client.put("clientVersion", clientType.clientVersion);
|
||||
client.put("deviceModel", clientType.deviceModel);
|
||||
|
||||
@@ -36,20 +36,40 @@ import app.revanced.extension.shared.spoof.ClientType;
|
||||
public class StreamingDataRequest {
|
||||
|
||||
private static final ClientType[] CLIENT_ORDER_TO_USE;
|
||||
|
||||
static {
|
||||
ClientType[] allClientTypes = ClientType.values();
|
||||
ClientType preferredClient = BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get();
|
||||
|
||||
CLIENT_ORDER_TO_USE = new ClientType[allClientTypes.length];
|
||||
CLIENT_ORDER_TO_USE[0] = preferredClient;
|
||||
|
||||
int i = 1;
|
||||
for (ClientType c : allClientTypes) {
|
||||
if (c != preferredClient) {
|
||||
CLIENT_ORDER_TO_USE[i++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final String AUTHORIZATION_HEADER = "Authorization";
|
||||
|
||||
private static final String[] REQUEST_HEADER_KEYS = {
|
||||
AUTHORIZATION_HEADER, // Available only to logged-in users.
|
||||
"X-GOOG-API-FORMAT-VERSION",
|
||||
"X-Goog-Visitor-Id"
|
||||
};
|
||||
|
||||
/**
|
||||
* TCP connection and HTTP read timeout.
|
||||
*/
|
||||
private static final int HTTP_TIMEOUT_MILLISECONDS = 10 * 1000;
|
||||
|
||||
/**
|
||||
* Any arbitrarily large value, but must be at least twice {@link #HTTP_TIMEOUT_MILLISECONDS}
|
||||
*/
|
||||
private static final int MAX_MILLISECONDS_TO_WAIT_FOR_FETCH = 20 * 1000;
|
||||
|
||||
private static final Map<String, StreamingDataRequest> cache = Collections.synchronizedMap(
|
||||
new LinkedHashMap<>(100) {
|
||||
/**
|
||||
@@ -67,22 +87,15 @@ public class StreamingDataRequest {
|
||||
}
|
||||
});
|
||||
|
||||
static {
|
||||
ClientType[] allClientTypes = ClientType.values();
|
||||
ClientType preferredClient = BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get();
|
||||
private static volatile ClientType lastSpoofedClientType;
|
||||
|
||||
CLIENT_ORDER_TO_USE = new ClientType[allClientTypes.length];
|
||||
CLIENT_ORDER_TO_USE[0] = preferredClient;
|
||||
|
||||
int i = 1;
|
||||
for (ClientType c : allClientTypes) {
|
||||
if (c != preferredClient) {
|
||||
CLIENT_ORDER_TO_USE[i++] = c;
|
||||
}
|
||||
}
|
||||
public static String getLastSpoofedClientName() {
|
||||
ClientType client = lastSpoofedClientType;
|
||||
return client == null ? "Unknown" : client.friendlyName;
|
||||
}
|
||||
|
||||
private final String videoId;
|
||||
|
||||
private final Future<ByteBuffer> future;
|
||||
|
||||
private StreamingDataRequest(String videoId, Map<String, String> playerHeaders) {
|
||||
@@ -178,7 +191,9 @@ public class StreamingDataRequest {
|
||||
// gzip encoding doesn't response with content length (-1),
|
||||
// but empty response body does.
|
||||
if (connection.getContentLength() == 0) {
|
||||
Logger.printDebug(() -> "Received empty response for video: " + videoId);
|
||||
if (BaseSettings.DEBUG.get()) {
|
||||
Logger.printException(() -> "Ignoring empty client: " + clientType);
|
||||
}
|
||||
} else {
|
||||
try (InputStream inputStream = new BufferedInputStream(connection.getInputStream());
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
||||
@@ -188,6 +203,7 @@ public class StreamingDataRequest {
|
||||
while ((bytesRead = inputStream.read(buffer)) >= 0) {
|
||||
baos.write(buffer, 0, bytesRead);
|
||||
}
|
||||
lastSpoofedClientType = clientType;
|
||||
|
||||
return ByteBuffer.wrap(baos.toByteArray());
|
||||
}
|
||||
@@ -198,7 +214,8 @@ public class StreamingDataRequest {
|
||||
}
|
||||
}
|
||||
|
||||
handleConnectionError("Could not fetch any client streams", null, debugEnabled);
|
||||
lastSpoofedClientType = null;
|
||||
handleConnectionError("Could not fetch any client streams", null, true);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class FixPlaybackSpeedWhilePlayingPatch {
|
||||
|
||||
private static final float DEFAULT_YOUTUBE_PLAYBACK_SPEED = 1.0f;
|
||||
|
||||
public static boolean playbackSpeedChanged(float playbackSpeed) {
|
||||
if (playbackSpeed == DEFAULT_YOUTUBE_PLAYBACK_SPEED &&
|
||||
PlayerType.getCurrent().isMaximizedOrFullscreen()) {
|
||||
|
||||
Logger.printDebug(() -> "Blocking call to change playback speed to 1.0x");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import app.revanced.extension.youtube.settings.Settings;
|
||||
@SuppressWarnings("unused")
|
||||
public class ForceOriginalAudioPatch {
|
||||
|
||||
private static final String DEFAULT_AUDIO_TRACKS_IDENTIFIER = "original";
|
||||
private static final String DEFAULT_AUDIO_TRACKS_SUFFIX = ".4";
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
@@ -17,7 +17,7 @@ public class ForceOriginalAudioPatch {
|
||||
return isDefault;
|
||||
}
|
||||
|
||||
if (audioTrackDisplayName.isEmpty()) {
|
||||
if (audioTrackId.isEmpty()) {
|
||||
// Older app targets can have empty audio tracks and these might be placeholders.
|
||||
// The real audio tracks are called after these.
|
||||
return isDefault;
|
||||
@@ -26,7 +26,7 @@ public class ForceOriginalAudioPatch {
|
||||
Logger.printDebug(() -> "default: " + String.format("%-5s", isDefault) + " id: "
|
||||
+ String.format("%-8s", audioTrackId) + " name:" + audioTrackDisplayName);
|
||||
|
||||
final boolean isOriginal = audioTrackDisplayName.contains(DEFAULT_AUDIO_TRACKS_IDENTIFIER);
|
||||
final boolean isOriginal = audioTrackId.endsWith(DEFAULT_AUDIO_TRACKS_SUFFIX);
|
||||
if (isOriginal) {
|
||||
Logger.printDebug(() -> "Using audio: " + audioTrackId);
|
||||
}
|
||||
@@ -34,8 +34,8 @@ public class ForceOriginalAudioPatch {
|
||||
return isOriginal;
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "isDefaultAudioStream failure", ex);
|
||||
}
|
||||
|
||||
return isDefault;
|
||||
return isDefault;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButton;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class OpenShortsInRegularPlayerPatch {
|
||||
|
||||
public enum ShortsPlayerType {
|
||||
SHORTS_PLAYER,
|
||||
REGULAR_PLAYER,
|
||||
REGULAR_PLAYER_FULLSCREEN
|
||||
}
|
||||
|
||||
static {
|
||||
if (!VersionCheckPatch.IS_19_46_OR_GREATER
|
||||
&& Settings.SHORTS_PLAYER_TYPE.get() == ShortsPlayerType.REGULAR_PLAYER_FULLSCREEN) {
|
||||
// User imported newer settings to an older app target.
|
||||
Logger.printInfo(() -> "Resetting " + Settings.SHORTS_PLAYER_TYPE);
|
||||
Settings.SHORTS_PLAYER_TYPE.resetToDefault();
|
||||
}
|
||||
}
|
||||
|
||||
private static WeakReference<Activity> mainActivityRef = new WeakReference<>(null);
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void setMainActivity(Activity activity) {
|
||||
mainActivityRef = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean openShort(String videoID) {
|
||||
try {
|
||||
ShortsPlayerType type = Settings.SHORTS_PLAYER_TYPE.get();
|
||||
if (type == ShortsPlayerType.SHORTS_PLAYER) {
|
||||
return false; // Default unpatched behavior.
|
||||
}
|
||||
|
||||
if (videoID.isEmpty()) {
|
||||
// Shorts was opened using launcher app shortcut.
|
||||
//
|
||||
// This check will not detect if the Shorts app shortcut is used
|
||||
// while the app is running in the background (instead the regular player is opened).
|
||||
// To detect that the hooked method map parameter can be checked
|
||||
// if integer key 'com.google.android.apps.youtube.app.endpoint.flags'
|
||||
// has bitmask 16 set.
|
||||
//
|
||||
// This use case seems unlikely if the user has the Shorts
|
||||
// set to open in the regular player, so it's ignored as
|
||||
// checking the map makes the patch more complicated.
|
||||
Logger.printDebug(() -> "Ignoring Short with no videoId");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NavigationButton.getSelectedNavigationButton() == NavigationButton.SHORTS) {
|
||||
return false; // Always use Shorts player for the Shorts nav button.
|
||||
}
|
||||
|
||||
final boolean forceFullScreen = (type == ShortsPlayerType.REGULAR_PLAYER_FULLSCREEN);
|
||||
OpenVideosFullscreenHookPatch.setOpenNextVideoFullscreen(forceFullScreen);
|
||||
|
||||
// Can use the application context and add intent flags of
|
||||
// FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_CLEAR_TOP
|
||||
// But the activity context seems to fix random app crashes
|
||||
// if Shorts urls are opened outside the app.
|
||||
var context = mainActivityRef.get();
|
||||
|
||||
Intent videoPlayerIntent = new Intent(
|
||||
Intent.ACTION_VIEW,
|
||||
Uri.parse("https://youtube.com/watch?v=" + videoID)
|
||||
);
|
||||
videoPlayerIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
videoPlayerIntent.setPackage(context.getPackageName());
|
||||
|
||||
context.startActivity(videoPlayerIntent);
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
OpenVideosFullscreenHookPatch.setOpenNextVideoFullscreen(null);
|
||||
Logger.printException(() -> "openShort failure", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class OpenVideosFullscreen {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean openVideoFullscreenPortrait(boolean original) {
|
||||
return Settings.OPEN_VIDEOS_FULLSCREEN_PORTRAIT.get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class OpenVideosFullscreenHookPatch {
|
||||
|
||||
@Nullable
|
||||
private static volatile Boolean openNextVideoFullscreen;
|
||||
|
||||
public static void setOpenNextVideoFullscreen(@Nullable Boolean forceFullScreen) {
|
||||
openNextVideoFullscreen = forceFullScreen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changed during patching since this class is also
|
||||
* used by {@link OpenVideosFullscreenHookPatch}.
|
||||
*/
|
||||
private static boolean isFullScreenPatchIncluded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean openVideoFullscreenPortrait(boolean original) {
|
||||
Boolean openFullscreen = openNextVideoFullscreen;
|
||||
if (openFullscreen != null) {
|
||||
openNextVideoFullscreen = null;
|
||||
return openFullscreen;
|
||||
}
|
||||
|
||||
if (!isFullScreenPatchIncluded()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Settings.OPEN_VIDEOS_FULLSCREEN_PORTRAIT.get();
|
||||
}
|
||||
}
|
||||
@@ -9,4 +9,5 @@ public class VersionCheckPatch {
|
||||
public static final boolean IS_19_26_OR_GREATER = Utils.getAppVersionName().compareTo("19.26.00") >= 0;
|
||||
public static final boolean IS_19_29_OR_GREATER = Utils.getAppVersionName().compareTo("19.29.00") >= 0;
|
||||
public static final boolean IS_19_34_OR_GREATER = Utils.getAppVersionName().compareTo("19.34.00") >= 0;
|
||||
public static final boolean IS_19_46_OR_GREATER = Utils.getAppVersionName().compareTo("19.46.00") >= 0;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import static app.revanced.extension.shared.settings.Setting.migrateFromOldPrefe
|
||||
import static app.revanced.extension.shared.settings.Setting.migrateOldSettingToNew;
|
||||
import static app.revanced.extension.shared.settings.Setting.parent;
|
||||
import static app.revanced.extension.shared.settings.Setting.parentsAny;
|
||||
import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.NotSpoofingAndroidAvailability;
|
||||
import static app.revanced.extension.youtube.patches.ChangeStartPagePatch.StartPage;
|
||||
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHideExpandCloseAvailability;
|
||||
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHorizontalDragAvailability;
|
||||
@@ -16,6 +17,7 @@ import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerT
|
||||
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.OpenShortsInRegularPlayerPatch.ShortsPlayerType;
|
||||
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,7 +54,7 @@ public class Settings extends BaseSettings {
|
||||
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);
|
||||
public static final BooleanSetting FORCE_ORIGINAL_AUDIO = new BooleanSetting("revanced_force_original_audio", FALSE, new NotSpoofingAndroidAvailability());
|
||||
|
||||
// Ads
|
||||
public static final BooleanSetting HIDE_BUTTONED_ADS = new BooleanSetting("revanced_hide_buttoned_ads", TRUE);
|
||||
@@ -224,6 +226,7 @@ public class Settings extends BaseSettings {
|
||||
// Shorts
|
||||
public static final BooleanSetting DISABLE_RESUMING_SHORTS_PLAYER = new BooleanSetting("revanced_disable_resuming_shorts_player", FALSE);
|
||||
public static final BooleanSetting DISABLE_SHORTS_BACKGROUND_PLAYBACK = new BooleanSetting("revanced_shorts_disable_background_playback", FALSE);
|
||||
public static final EnumSetting<ShortsPlayerType> SHORTS_PLAYER_TYPE = new EnumSetting<>("revanced_shorts_player_type", ShortsPlayerType.SHORTS_PLAYER);
|
||||
public static final BooleanSetting HIDE_SHORTS_CHANNEL_BAR = new BooleanSetting("revanced_hide_shorts_channel_bar", FALSE);
|
||||
public static final BooleanSetting HIDE_SHORTS_COMMENTS_BUTTON = new BooleanSetting("revanced_hide_shorts_comments_button", FALSE);
|
||||
public static final BooleanSetting HIDE_SHORTS_DISLIKE_BUTTON = new BooleanSetting("revanced_hide_shorts_dislike_button", FALSE);
|
||||
|
||||
@@ -77,8 +77,10 @@ public class SpoofStreamingDataSideEffectsPreference extends Preference {
|
||||
Logger.printDebug(() -> "Updating spoof stream side effects preference");
|
||||
setEnabled(BaseSettings.SPOOF_VIDEO_STREAMS.get());
|
||||
|
||||
String key = "revanced_spoof_video_streams_about_"
|
||||
+ clientType.name().toLowerCase();
|
||||
String key = "revanced_spoof_video_streams_about_" +
|
||||
(clientType == ClientType.IOS_UNPLUGGED
|
||||
? "ios_tv"
|
||||
: "android");
|
||||
setTitle(str(key + "_title"));
|
||||
setSummary(str(key + "_summary"));
|
||||
}
|
||||
|
||||
@@ -150,11 +150,16 @@ public class SBRequester {
|
||||
String end = String.format(Locale.US, TIME_TEMPLATE, endTime / 1000f);
|
||||
String duration = String.format(Locale.US, TIME_TEMPLATE, videoLength / 1000f);
|
||||
|
||||
HttpURLConnection connection = getConnectionFromRoute(SBRoutes.SUBMIT_SEGMENTS, privateUserId, videoId, category, start, end, duration);
|
||||
HttpURLConnection connection = getConnectionFromRoute(SBRoutes.SUBMIT_SEGMENTS,
|
||||
privateUserId, videoId, category, start, end, duration);
|
||||
final int responseCode = connection.getResponseCode();
|
||||
|
||||
String userMessage = switch (responseCode) {
|
||||
case HTTP_STATUS_CODE_SUCCESS -> str("revanced_sb_submit_succeeded");
|
||||
if (responseCode == HTTP_STATUS_CODE_SUCCESS) {
|
||||
Utils.showToastLong(str("revanced_sb_submit_succeeded"));
|
||||
return;
|
||||
}
|
||||
|
||||
String userErrorMessage = switch (responseCode) {
|
||||
case 409 -> str("revanced_sb_submit_failed_duplicate");
|
||||
case 403 -> str("revanced_sb_submit_failed_forbidden",
|
||||
Requester.parseErrorStringAndDisconnect(connection));
|
||||
@@ -167,7 +172,7 @@ public class SBRequester {
|
||||
|
||||
// Message might be about the users account or an error too large to show in a toast.
|
||||
// Use a dialog instead.
|
||||
SponsorBlockUtils.showErrorDialog(userMessage);
|
||||
SponsorBlockUtils.showErrorDialog(userErrorMessage);
|
||||
} catch (SocketTimeoutException ex) {
|
||||
Logger.printDebug(() -> "Timeout", ex);
|
||||
Utils.showToastLong(str("revanced_sb_submit_failed_timeout"));
|
||||
|
||||
@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
|
||||
org.gradle.parallel = true
|
||||
android.useAndroidX = true
|
||||
kotlin.code.style = official
|
||||
version = 5.5.2-dev.2
|
||||
version = 5.7.2-dev.1
|
||||
|
||||
@@ -1177,6 +1177,10 @@ public final class app/revanced/patches/youtube/layout/player/background/PlayerC
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenKt {
|
||||
public static final fun getOpenVideosFullscreen ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenPatchKt {
|
||||
public static final fun getOpenVideosFullscreenPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
@@ -1210,6 +1214,10 @@ public final class app/revanced/patches/youtube/layout/shortsautoplay/ShortsAuto
|
||||
public static final fun getShortsAutoplayPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/shortsplayer/OpenShortsInRegularPlayerPatchKt {
|
||||
public static final fun getOpenShortsInRegularPlayerPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockPatchKt {
|
||||
public static final fun getSponsorBlockPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1288,6 +1296,10 @@ public final class app/revanced/patches/youtube/misc/fix/playback/UserAgentClien
|
||||
public static final fun getUserAgentClientSpoofPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/fix/playbackspeed/FIxPlaybackSpeedWhilePlayingPatchKt {
|
||||
public static final fun getFixPlaybackSpeedWhilePlayingPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatchKt {
|
||||
public static final fun getGmsCoreSupportPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package app.revanced.patches.shared.misc.checks
|
||||
|
||||
import android.os.Build.*
|
||||
import app.revanced.patcher.Fingerprint
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.encodedValue.MutableEncodedValue
|
||||
@@ -82,7 +82,7 @@ fun checkEnvironmentPatch(
|
||||
}
|
||||
}
|
||||
|
||||
fun invokeCheck() = mainActivityOnCreateFingerprint.method.addInstructions(
|
||||
fun invokeCheck() = mainActivityOnCreateFingerprint.method.addInstruction(
|
||||
0,
|
||||
"invoke-static/range { p0 .. p0 },$EXTENSION_CLASS_DESCRIPTOR->check(Landroid/app/Activity;)V",
|
||||
)
|
||||
|
||||
@@ -121,3 +121,19 @@ internal val hlsCurrentTimeFingerprint = fingerprint {
|
||||
HLS_CURRENT_TIME_FEATURE_FLAG
|
||||
}
|
||||
}
|
||||
|
||||
internal val nerdsStatsVideoFormatBuilderFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returns("Ljava/lang/String;")
|
||||
parameters("L")
|
||||
strings("codecs=\"")
|
||||
}
|
||||
|
||||
internal val patchIncludedExtensionMethodFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||
returns("Z")
|
||||
parameters()
|
||||
custom { method, classDef ->
|
||||
classDef.type == EXTENSION_CLASS_DESCRIPTOR && method.name == "isPatchIncluded"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,11 @@ import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.util.findInstructionIndicesReversedOrThrow
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.insertFeatureFlagBooleanOverride
|
||||
import app.revanced.util.returnEarly
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
||||
@@ -39,6 +41,12 @@ fun spoofVideoStreamsPatch(
|
||||
dependsOn(addResourcesPatch)
|
||||
|
||||
execute {
|
||||
// region Enable extension helper method used by other patches
|
||||
|
||||
patchIncludedExtensionMethodFingerprint.method.returnEarly(true)
|
||||
|
||||
// endregion
|
||||
|
||||
// region Block /initplayback requests to fall back to /get_watch requests.
|
||||
|
||||
val moveUriStringIndex = buildInitPlaybackRequestFingerprint.patternMatch!!.startIndex
|
||||
@@ -200,6 +208,25 @@ fun spoofVideoStreamsPatch(
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Append spoof info.
|
||||
|
||||
nerdsStatsVideoFormatBuilderFingerprint.method.apply {
|
||||
findInstructionIndicesReversedOrThrow(Opcode.RETURN_OBJECT).forEach { index ->
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
addInstructions(
|
||||
index,
|
||||
"""
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->appendSpoofedClient(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Fix iOS livestream current time.
|
||||
|
||||
@@ -11,8 +11,8 @@ import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||
import app.revanced.patches.twitter.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
||||
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.instruction.formats.Instruction35c
|
||||
|
||||
internal var tweetShareLinkTemplateId = -1L
|
||||
private set
|
||||
@@ -25,15 +25,7 @@ internal val changeLinkSharingDomainResourcePatch = resourcePatch {
|
||||
}
|
||||
}
|
||||
|
||||
// This method is used to build the link that is shared when the "Share via..." button is pressed.
|
||||
private const val FORMAT_METHOD_RESOURCE_REFERENCE =
|
||||
"Lapp/revanced/extension/twitter/patches/links/ChangeLinkSharingDomainPatch;->" +
|
||||
"formatResourceLink([Ljava/lang/Object;)Ljava/lang/String;"
|
||||
|
||||
// This method is used to build the link that is shared when the "Copy link" button is pressed.
|
||||
private const val FORMAT_METHOD_REFERENCE =
|
||||
"Lapp/revanced/extension/twitter/patches/links/ChangeLinkSharingDomainPatch;->" +
|
||||
"formatLink(JLjava/lang/String;)Ljava/lang/String;"
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/twitter/patches/links/ChangeLinkSharingDomainPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val changeLinkSharingDomainPatch = bytecodePatch(
|
||||
@@ -71,7 +63,7 @@ val changeLinkSharingDomainPatch = bytecodePatch(
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static { p0, p1, p2 }, $FORMAT_METHOD_REFERENCE
|
||||
invoke-static { p0, p1, p2 }, $EXTENSION_CLASS_DESCRIPTOR->formatLink(JLjava/lang/String;)Ljava/lang/String;
|
||||
move-result-object p0
|
||||
return-object p0
|
||||
""",
|
||||
@@ -84,12 +76,12 @@ val changeLinkSharingDomainPatch = bytecodePatch(
|
||||
|
||||
// Format the link with the new domain name register (1 instruction below the const).
|
||||
val formatLinkCallIndex = templateIdConstIndex + 1
|
||||
val formatLinkCall = getInstruction<Instruction35c>(formatLinkCallIndex)
|
||||
val register = getInstruction<FiveRegisterInstruction>(formatLinkCallIndex).registerE
|
||||
|
||||
// Replace the original method call with the new method call.
|
||||
replaceInstruction(
|
||||
formatLinkCallIndex,
|
||||
"invoke-static { v${formatLinkCall.registerE} }, $FORMAT_METHOD_RESOURCE_REFERENCE",
|
||||
"invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->formatResourceLink([Ljava/lang/Object;)Ljava/lang/String;",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ val hideAdsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ val hideGetPremiumPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ val videoAdsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ val copyVideoUrlPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ val removeViewerDiscretionDialogPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ val downloadsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ val disablePreciseSeekingGesturePatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ val enableSeekbarTappingPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ val enableSlideToSeekPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ val seekbarThumbnailsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ val swipeControlsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ val autoCaptionsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ val customBrandingPatch = resourcePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ val changeHeaderPatch = resourcePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ val hideButtonsPatch = resourcePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ val navigationButtonsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ val hidePlayerOverlayButtonsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ val hideEndscreenCardsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ val disableFullscreenAmbientModePatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -133,6 +133,7 @@ val hideLayoutComponentsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ val hideInfoCardsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ val hidePlayerFlyoutMenuPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ val disableRollingNumberAnimationPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ val hideSeekbarPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -190,6 +190,7 @@ val hideShortsComponentsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ val disableSuggestedVideoEndScreenPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ val hideTimestampPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -170,6 +170,7 @@ val miniplayerPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ val playerPopupPanelsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ val playerControlsBackgroundPatch = resourcePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -14,3 +14,15 @@ internal val openVideosFullscreenPortraitFingerprint = fingerprint {
|
||||
OPEN_VIDEOS_FULLSCREEN_PORTRAIT_FEATURE_FLAG
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to enable opening regular videos fullscreen.
|
||||
*/
|
||||
internal val openVideosFullscreenHookPatchExtensionFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||
returns("Z")
|
||||
parameters()
|
||||
custom { methodDef, classDef ->
|
||||
methodDef.name == "isFullScreenPatchIncluded" && classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,46 +1,9 @@
|
||||
package app.revanced.patches.youtube.layout.player.fullscreen
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.util.insertFeatureFlagBooleanOverride
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/OpenVideosFullscreen;"
|
||||
|
||||
@Suppress("unused")
|
||||
val openVideosFullscreenPatch = bytecodePatch(
|
||||
name = "Open videos fullscreen",
|
||||
description = "Adds an option to open videos in full screen portrait mode.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.46.42",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
openVideosFullscreenPortraitFingerprint.method.insertFeatureFlagBooleanOverride(
|
||||
OPEN_VIDEOS_FULLSCREEN_PORTRAIT_FEATURE_FLAG,
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->openVideoFullscreenPortrait(Z)Z"
|
||||
)
|
||||
|
||||
// Add resources and setting last, in case the user force patches an old incompatible version.
|
||||
|
||||
addResources("youtube", "layout.player.fullscreen.openVideosFullscreen")
|
||||
|
||||
PreferenceScreen.PLAYER.addPreferences(
|
||||
SwitchPreference("revanced_open_videos_fullscreen_portrait")
|
||||
)
|
||||
}
|
||||
}
|
||||
@Deprecated("Renamed to openVideosFullscreenPatch", ReplaceWith("openVideosFullscreenPatch"))
|
||||
val openVideosFullscreen = bytecodePatch{
|
||||
dependsOn(openVideosFullscreenPatch)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package app.revanced.patches.youtube.layout.player.fullscreen
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.youtube.layout.shortsplayer.openShortsInRegularPlayerPatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_46_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.util.insertFeatureFlagBooleanOverride
|
||||
|
||||
internal const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/OpenVideosFullscreenHookPatch;"
|
||||
|
||||
/**
|
||||
* Used by both [openVideosFullscreenPatch] and [openShortsInRegularPlayerPatch].
|
||||
*/
|
||||
internal val openVideosFullscreenHookPatch = bytecodePatch {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
versionCheckPatch
|
||||
)
|
||||
|
||||
execute {
|
||||
if (!is_19_46_or_greater) {
|
||||
return@execute
|
||||
}
|
||||
|
||||
openVideosFullscreenPortraitFingerprint.method.insertFeatureFlagBooleanOverride(
|
||||
OPEN_VIDEOS_FULLSCREEN_PORTRAIT_FEATURE_FLAG,
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->openVideoFullscreenPortrait(Z)Z"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package app.revanced.patches.youtube.layout.player.fullscreen
|
||||
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_46_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.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
val openVideosFullscreenPatch = bytecodePatch(
|
||||
name = "Open videos fullscreen",
|
||||
description = "Adds an option to open videos in full screen portrait mode.",
|
||||
) {
|
||||
dependsOn(
|
||||
openVideosFullscreenHookPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
versionCheckPatch
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
if (!is_19_46_or_greater) {
|
||||
throw PatchException("'Open videos fullscreen' requires 19.46.42 or greater")
|
||||
}
|
||||
|
||||
addResources("youtube", "layout.player.fullscreen.openVideosFullscreen")
|
||||
|
||||
PreferenceScreen.PLAYER.addPreferences(
|
||||
SwitchPreference("revanced_open_videos_fullscreen_portrait")
|
||||
)
|
||||
|
||||
// Enable the logic for the user Setting to open regular videos fullscreen.
|
||||
openVideosFullscreenHookPatchExtensionFingerprint.method.returnEarly(true)
|
||||
}
|
||||
}
|
||||
@@ -60,6 +60,7 @@ val customPlayerOverlayOpacityPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ val returnYouTubeDislikePatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ val wideSearchbarPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.revanced.patches.youtube.layout.shortsautoplay
|
||||
|
||||
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.patch.bytecodePatch
|
||||
@@ -39,6 +40,7 @@ val shortsAutoplayPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
@@ -56,7 +58,7 @@ val shortsAutoplayPatch = bytecodePatch(
|
||||
}
|
||||
|
||||
// Main activity is used to check if app is in pip mode.
|
||||
mainActivityOnCreateFingerprint.method.addInstructions(
|
||||
mainActivityOnCreateFingerprint.method.addInstruction(
|
||||
1,
|
||||
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->" +
|
||||
"setMainActivity(Landroid/app/Activity;)V",
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package app.revanced.patches.youtube.layout.shortsplayer
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
/**
|
||||
* Purpose of this method is not clear, and it's only used to identify
|
||||
* the obfuscated name of the videoId() method in PlaybackStartDescriptor.
|
||||
*/
|
||||
internal val playbackStartFeatureFlagFingerprint = fingerprint {
|
||||
returns("Z")
|
||||
parameters(
|
||||
"Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;",
|
||||
)
|
||||
literal {
|
||||
45380134L
|
||||
}
|
||||
}
|
||||
|
||||
// Pre 19.25
|
||||
internal val shortsPlaybackIntentLegacyFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
parameters(
|
||||
"L",
|
||||
"Ljava/util/Map;",
|
||||
"J",
|
||||
"Ljava/lang/String;",
|
||||
"Z",
|
||||
"Ljava/util/Map;"
|
||||
)
|
||||
strings(
|
||||
// None of these strings are unique.
|
||||
"com.google.android.apps.youtube.app.endpoint.flags",
|
||||
"ReelWatchFragmentArgs",
|
||||
"reels_fragment_descriptor"
|
||||
)
|
||||
}
|
||||
|
||||
internal val shortsPlaybackIntentFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PROTECTED, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
parameters(
|
||||
"Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;",
|
||||
"Ljava/util/Map;",
|
||||
"J",
|
||||
"Ljava/lang/String;"
|
||||
)
|
||||
strings(
|
||||
// None of these strings are unique.
|
||||
"com.google.android.apps.youtube.app.endpoint.flags",
|
||||
"ReelWatchFragmentArgs",
|
||||
"reels_fragment_descriptor"
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package app.revanced.patches.youtube.layout.shortsplayer
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.ListPreference
|
||||
import app.revanced.patches.youtube.layout.player.fullscreen.openVideosFullscreenHookPatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
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.is_19_46_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.patches.youtube.shared.mainActivityOnCreateFingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
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
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/OpenShortsInRegularPlayerPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val openShortsInRegularPlayerPatch = bytecodePatch(
|
||||
name = "Open Shorts in regular player",
|
||||
description = "Adds options to open Shorts in the regular video player.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
openVideosFullscreenHookPatch,
|
||||
navigationBarHookPatch,
|
||||
versionCheckPatch
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"18.38.44",
|
||||
"18.49.37",
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("youtube", "layout.shortsplayer.shortsPlayerTypePatch")
|
||||
|
||||
PreferenceScreen.SHORTS.addPreferences(
|
||||
if (is_19_46_or_greater) {
|
||||
ListPreference(
|
||||
key = "revanced_shorts_player_type",
|
||||
summaryKey = null,
|
||||
)
|
||||
} else {
|
||||
ListPreference(
|
||||
key = "revanced_shorts_player_type",
|
||||
summaryKey = null,
|
||||
entriesKey = "revanced_shorts_player_type_legacy_entries",
|
||||
entryValuesKey = "revanced_shorts_player_type_legacy_entry_values"
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
// Activity is used as the context to launch an Intent.
|
||||
mainActivityOnCreateFingerprint.method.addInstruction(
|
||||
1,
|
||||
"invoke-static/range { p0 .. p0 }, ${EXTENSION_CLASS_DESCRIPTOR}->" +
|
||||
"setMainActivity(Landroid/app/Activity;)V",
|
||||
)
|
||||
|
||||
// Find the obfuscated method name for PlaybackStartDescriptor.videoId()
|
||||
val playbackStartVideoIdMethodName = playbackStartFeatureFlagFingerprint.method.let {
|
||||
val stringMethodIndex = it.indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.definingClass == "Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;"
|
||||
&& reference.returnType == "Ljava/lang/String;"
|
||||
}
|
||||
|
||||
navigate(it).to(stringMethodIndex).stop().name
|
||||
}
|
||||
|
||||
fun extensionInstructions(playbackStartRegister: Int, freeRegister: Int) =
|
||||
"""
|
||||
invoke-virtual { v$playbackStartRegister }, Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;->$playbackStartVideoIdMethodName()Ljava/lang/String;
|
||||
move-result-object v$freeRegister
|
||||
invoke-static { v$freeRegister }, $EXTENSION_CLASS_DESCRIPTOR->openShort(Ljava/lang/String;)Z
|
||||
move-result v$freeRegister
|
||||
if-eqz v$freeRegister, :disabled
|
||||
return-void
|
||||
|
||||
:disabled
|
||||
nop
|
||||
"""
|
||||
|
||||
if (!is_19_25_or_greater) {
|
||||
shortsPlaybackIntentLegacyFingerprint.method.apply {
|
||||
val index = indexOfFirstInstructionOrThrow {
|
||||
getReference<MethodReference>()?.returnType ==
|
||||
"Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;"
|
||||
}
|
||||
val freeRegister = getInstruction<FiveRegisterInstruction>(index).registerC
|
||||
val playbackStartRegister = getInstruction<OneRegisterInstruction>(index + 1).registerA
|
||||
|
||||
addInstructionsWithLabels(
|
||||
index + 2,
|
||||
extensionInstructions(playbackStartRegister, freeRegister)
|
||||
)
|
||||
}
|
||||
|
||||
return@execute
|
||||
}
|
||||
|
||||
shortsPlaybackIntentFingerprint.method.addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
move-object/from16 v0, p1
|
||||
${extensionInstructions(0, 1)}
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -119,6 +119,7 @@ val sponsorBlockPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ val spoofAppVersionPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ val changeStartPagePatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ val disableResumingShortsOnStartupPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ val enableTabletLayoutPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -163,22 +163,31 @@ val themePatch = bytecodePatch(
|
||||
}
|
||||
|
||||
// Fix the splash screen dark mode background color.
|
||||
// In earlier versions of the app this is white and makes no sense for dark mode.
|
||||
// This is only required for 19.32 and greater, but is applied to all targets.
|
||||
// Only dark mode needs this fix as light mode correctly uses the custom color.
|
||||
// In 19.32+ the dark mode splash screen is white and fades to black.
|
||||
// Maybe it's a bug in YT, or maybe it intentionally. Who knows.
|
||||
document("res/values-night/styles.xml").use { document ->
|
||||
// Create a night mode specific override for the splash screen background.
|
||||
val style = document.createElement("style")
|
||||
style.setAttribute("name", "Theme.YouTube.Home")
|
||||
style.setAttribute("parent", "@style/Base.V23.Theme.YouTube.Home")
|
||||
|
||||
val windowItem = document.createElement("item")
|
||||
windowItem.setAttribute("name", "android:windowBackground")
|
||||
windowItem.textContent = "@color/$splashBackgroundColor"
|
||||
style.appendChild(windowItem)
|
||||
|
||||
val resourcesNode = document.getElementsByTagName("resources").item(0) as Element
|
||||
resourcesNode.appendChild(style)
|
||||
val childNodes = resourcesNode.childNodes
|
||||
|
||||
for (i in 0 until childNodes.length) {
|
||||
val node = childNodes.item(i) as? Element ?: continue
|
||||
val nodeAttributeName = node.getAttribute("name")
|
||||
if (nodeAttributeName.startsWith("Theme.YouTube.Launcher")) {
|
||||
val nodeAttributeParent = node.getAttribute("parent")
|
||||
|
||||
val style = document.createElement("style")
|
||||
style.setAttribute("name", "Theme.YouTube.Home")
|
||||
style.setAttribute("parent", nodeAttributeParent)
|
||||
|
||||
val windowItem = document.createElement("item")
|
||||
windowItem.setAttribute("name", "android:windowBackground")
|
||||
windowItem.textContent = "@color/$splashBackgroundColor"
|
||||
style.appendChild(windowItem)
|
||||
|
||||
resourcesNode.removeChild(node)
|
||||
resourcesNode.appendChild(style)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -198,6 +207,7 @@ val themePatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ val alternativeThumbnailsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ val bypassImageRegionRestrictionsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package app.revanced.patches.youtube.misc.announcements
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
@@ -31,6 +31,7 @@ val announcementsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
@@ -41,7 +42,7 @@ val announcementsPatch = bytecodePatch(
|
||||
SwitchPreference("revanced_announcements"),
|
||||
)
|
||||
|
||||
mainActivityOnCreateFingerprint.method.addInstructions(
|
||||
mainActivityOnCreateFingerprint.method.addInstruction(
|
||||
// Insert index must be greater than the insert index used by GmsCoreSupport,
|
||||
// as both patch the same method and GmsCore check should be first.
|
||||
1,
|
||||
|
||||
@@ -32,6 +32,7 @@ val autoRepeatPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ val backgroundPlaybackPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ val enableDebuggingPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ val spoofDeviceDimensionsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package app.revanced.patches.youtube.misc.dns
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
@@ -13,7 +14,10 @@ val checkWatchHistoryDomainNameResolutionPatch = bytecodePatch(
|
||||
name = "Check watch history domain name resolution",
|
||||
description = "Checks if the device DNS server is preventing user watch history from being saved.",
|
||||
) {
|
||||
dependsOn(addResourcesPatch)
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
addResourcesPatch
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
@@ -25,13 +29,14 @@ val checkWatchHistoryDomainNameResolutionPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("youtube", "misc.dns.checkWatchHistoryDomainNameResolutionPatch")
|
||||
|
||||
mainActivityOnCreateFingerprint.method.addInstructions(
|
||||
mainActivityOnCreateFingerprint.method.addInstruction(
|
||||
// FIXME: Insert index must be greater than the insert index used by GmsCoreSupport,
|
||||
// as both patch the same method and GmsCoreSupport check should be first,
|
||||
// but the patch does not depend on GmsCoreSupport, so it should not be possible to enforce this
|
||||
|
||||
@@ -15,22 +15,16 @@ internal val onBackPressedFingerprint = fingerprint {
|
||||
}
|
||||
}
|
||||
|
||||
internal val recyclerViewScrollingFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL)
|
||||
internal val scrollPositionFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PROTECTED, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
parameters()
|
||||
parameters("L")
|
||||
opcodes(
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.CHECK_CAST,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_LEZ,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.CONST_4,
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.RETURN_VOID
|
||||
)
|
||||
strings("scroll_position")
|
||||
}
|
||||
|
||||
internal val recyclerViewTopScrollingFingerprint = fingerprint {
|
||||
|
||||
@@ -1,54 +1,49 @@
|
||||
package app.revanced.patches.youtube.misc.fix.backtoexitgesture
|
||||
|
||||
import app.revanced.patcher.Fingerprint
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/FixBackToExitGesturePatch;"
|
||||
|
||||
internal val fixBackToExitGesturePatch = bytecodePatch(
|
||||
description = "Fixes the swipe back to exit gesture.",
|
||||
) {
|
||||
|
||||
execute {
|
||||
/**
|
||||
* Inject a call to a method from the extension.
|
||||
*
|
||||
* @param targetMethod The target method to call.
|
||||
*/
|
||||
fun Fingerprint.injectCall(targetMethod: ExtensionMethod) = method.addInstruction(
|
||||
patternMatch!!.endIndex,
|
||||
targetMethod.toString(),
|
||||
)
|
||||
recyclerViewTopScrollingFingerprint.match(recyclerViewTopScrollingParentFingerprint.originalClassDef)
|
||||
.let {
|
||||
it.method.addInstruction(
|
||||
it.patternMatch!!.endIndex,
|
||||
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->onTopView()V"
|
||||
)
|
||||
}
|
||||
|
||||
mapOf(
|
||||
recyclerViewTopScrollingFingerprint.also {
|
||||
it.match(recyclerViewTopScrollingParentFingerprint.originalClassDef)
|
||||
} to ExtensionMethod(
|
||||
methodName = "onTopView",
|
||||
),
|
||||
recyclerViewScrollingFingerprint to ExtensionMethod(
|
||||
methodName = "onScrollingViews",
|
||||
),
|
||||
onBackPressedFingerprint to ExtensionMethod(
|
||||
"p0",
|
||||
"onBackPressed",
|
||||
"Landroid/app/Activity;",
|
||||
),
|
||||
).forEach { (fingerprint, target) -> fingerprint.injectCall(target) }
|
||||
scrollPositionFingerprint.let {
|
||||
navigate(it.originalMethod)
|
||||
.to(it.patternMatch!!.startIndex + 1)
|
||||
.stop().apply {
|
||||
val index = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.INVOKE_VIRTUAL && getReference<MethodReference>()?.definingClass ==
|
||||
"Landroid/support/v7/widget/RecyclerView;"
|
||||
}
|
||||
|
||||
addInstruction(
|
||||
index,
|
||||
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->onScrollingViews()V"
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onBackPressedFingerprint.let {
|
||||
it.method.addInstruction(
|
||||
it.patternMatch!!.endIndex,
|
||||
"invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->onBackPressed(Landroid/app/Activity;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A reference to a method from the extension for [fixBackToExitGesturePatch].
|
||||
*
|
||||
* @param register The method registers.
|
||||
* @param methodName The method name.
|
||||
* @param parameterTypes The parameters of the method.
|
||||
*/
|
||||
private class ExtensionMethod(
|
||||
val register: String = "",
|
||||
val methodName: String,
|
||||
val parameterTypes: String = "",
|
||||
) {
|
||||
override fun toString() =
|
||||
"invoke-static {$register}, Lapp/revanced/extension/youtube/patches/FixBackToExitGesturePatch;->$methodName($parameterTypes)V"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package app.revanced.patches.youtube.misc.fix.playbackspeed
|
||||
|
||||
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.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/FixPlaybackSpeedWhilePlayingPatch;"
|
||||
|
||||
/**
|
||||
* Fixes a bug in YouTube 19.34+ where the playback speed
|
||||
* can incorrectly reset to 1.0x under certain conditions.
|
||||
*
|
||||
* Reproduction steps using 19.34+
|
||||
* 1. Open a video and start playback
|
||||
* 2. Change the speed to any value that is not 1.0x.
|
||||
* 3. Open the comments panel.
|
||||
* 4. Tap any "N more replies" link at the bottom of a comment, or tap on a timestamp of a comment.
|
||||
* 5. Pause the video
|
||||
* 6. Resume the video
|
||||
* 7. Playback speed will incorrectly change to 1.0x.
|
||||
*/
|
||||
@Suppress("unused")
|
||||
val fixPlaybackSpeedWhilePlayingPatch = bytecodePatch{
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
playerTypeHookPatch,
|
||||
versionCheckPatch,
|
||||
)
|
||||
|
||||
execute {
|
||||
if (!is_19_34_or_greater) {
|
||||
return@execute
|
||||
}
|
||||
|
||||
playbackSpeedInFeedsFingerprint.method.apply {
|
||||
val freeRegister = implementation!!.registerCount - parameters.size - 2
|
||||
val playbackSpeedIndex = indexOfGetPlaybackSpeedInstruction(this)
|
||||
val playbackSpeedRegister = getInstruction<TwoRegisterInstruction>(playbackSpeedIndex).registerA
|
||||
val returnIndex = indexOfFirstInstructionOrThrow(playbackSpeedIndex, Opcode.RETURN_VOID)
|
||||
|
||||
addInstructionsWithLabels(
|
||||
playbackSpeedIndex + 1,
|
||||
"""
|
||||
invoke-static { v$playbackSpeedRegister }, $EXTENSION_CLASS_DESCRIPTOR->playbackSpeedChanged(F)Z
|
||||
move-result v$freeRegister
|
||||
if-nez v$freeRegister, :do_not_change
|
||||
""",
|
||||
ExternalLabel("do_not_change", getInstruction(returnIndex))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package app.revanced.patches.youtube.misc.fix.playbackspeed
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionReversed
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
/**
|
||||
* This method is usually used to set the initial speed (1.0x) when playback starts from the feed.
|
||||
* For some reason, in the latest YouTube, it is invoked even after the video has already started.
|
||||
*/
|
||||
internal val playbackSpeedInFeedsFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
parameters("L")
|
||||
opcodes(
|
||||
Opcode.IGET,
|
||||
Opcode.MUL_INT_LIT16,
|
||||
Opcode.IGET_WIDE,
|
||||
Opcode.CONST_WIDE_16,
|
||||
Opcode.CMP_LONG,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.IF_LEZ,
|
||||
Opcode.SUB_LONG_2ADDR,
|
||||
)
|
||||
custom { method, _ ->
|
||||
indexOfGetPlaybackSpeedInstruction(method) >= 0
|
||||
}
|
||||
}
|
||||
|
||||
internal fun indexOfGetPlaybackSpeedInstruction(method: Method) =
|
||||
method.indexOfFirstInstructionReversed {
|
||||
opcode == Opcode.IGET &&
|
||||
getReference<FieldReference>()?.type == "F"
|
||||
}
|
||||
@@ -43,6 +43,7 @@ val gmsCoreSupportPatch = gmsCoreSupportPatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ val bypassURLRedirectsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ val openLinksExternallyPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ val removeTrackingQueryParameterPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import app.revanced.patches.shared.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.misc.check.checkEnvironmentPatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.fix.cairo.disableCairoSettingsPatch
|
||||
import app.revanced.patches.youtube.misc.fix.playbackspeed.fixPlaybackSpeedWhilePlayingPatch
|
||||
import app.revanced.util.*
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
@@ -118,6 +119,7 @@ val settingsPatch = bytecodePatch(
|
||||
settingsResourcePatch,
|
||||
addResourcesPatch,
|
||||
disableCairoSettingsPatch,
|
||||
fixPlaybackSpeedWhilePlayingPatch,
|
||||
// Currently there is no easy way to make a mandatory patch,
|
||||
// so for now this is a dependent of this patch.
|
||||
checkEnvironmentPatch,
|
||||
|
||||
@@ -20,6 +20,7 @@ val spoofVideoStreamsPatch = spoofVideoStreamsPatch({
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
@@ -37,19 +38,20 @@ val spoofVideoStreamsPatch = spoofVideoStreamsPatch({
|
||||
preferences = setOf(
|
||||
SwitchPreference("revanced_spoof_video_streams"),
|
||||
ListPreference(
|
||||
"revanced_spoof_video_streams_client",
|
||||
"revanced_spoof_video_streams_client_type",
|
||||
summaryKey = null,
|
||||
),
|
||||
NonInteractivePreference(
|
||||
// Requires a key and title but the actual text is chosen at runtime.
|
||||
key = "revanced_spoof_video_streams_about_android",
|
||||
tag = "app.revanced.extension.youtube.settings.preference.SpoofStreamingDataSideEffectsPreference"
|
||||
),
|
||||
ListPreference(
|
||||
"revanced_spoof_video_streams_language",
|
||||
summaryKey = null
|
||||
),
|
||||
SwitchPreference("revanced_spoof_video_streams_ios_force_avc"),
|
||||
// Preference requires a title but the actual text is chosen at runtime.
|
||||
NonInteractivePreference(
|
||||
key = "revanced_spoof_video_streams_about_android_vr",
|
||||
tag = "app.revanced.extension.youtube.settings.preference.SpoofStreamingDataSideEffectsPreference"
|
||||
),
|
||||
SwitchPreference("revanced_spoof_streaming_data_stats_for_nerds"),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -29,6 +29,7 @@ val zoomHapticsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ val forceOriginalAudioPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ val rememberVideoQualityPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ val playbackSpeedPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ val restoreOldVideoQualityMenuPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.45.38",
|
||||
"19.46.42",
|
||||
"19.47.53",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -164,6 +164,8 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.startupshortsreset.disableResumingShortsOnStartupPatch">
|
||||
</patch>
|
||||
<patch id="layout.shortsplayer.shortsPlayerTypePatch">
|
||||
</patch>
|
||||
<patch id="layout.shortsautoplay.shortsAutoplayPatch">
|
||||
</patch>
|
||||
<patch id="layout.tablet.enableTabletLayoutPatch">
|
||||
|
||||
@@ -164,6 +164,8 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.startupshortsreset.disableResumingShortsOnStartupPatch">
|
||||
</patch>
|
||||
<patch id="layout.shortsplayer.shortsPlayerTypePatch">
|
||||
</patch>
|
||||
<patch id="layout.shortsautoplay.shortsAutoplayPatch">
|
||||
</patch>
|
||||
<patch id="layout.tablet.enableTabletLayoutPatch">
|
||||
|
||||
@@ -1049,6 +1049,12 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_disable_resuming_shorts_player_summary_on">ŲŲ ŲØĒŲ
Ø§ØŗØĒØĻŲØ§Ų ØĒØ´ØēŲŲ Ų
Ø´ØēŲ Shorts ØšŲØ¯ Ø¨Ø¯ØĄ ØĒØ´ØēŲŲ Ø§ŲØĒØˇØ¨ŲŲ</string>
|
||||
<string name="revanced_disable_resuming_shorts_player_summary_off">ØŗŲØĒŲ
Ø§ØŗØĒØĻŲØ§Ų ØĒØ´ØēŲŲ Ų
Ø´ØēŲ Shorts ØšŲØ¯ Ø¨Ø¯ØĄ ØĒØ´ØēŲŲ Ø§ŲØĒØˇØ¨ŲŲ</string>
|
||||
</patch>
|
||||
<patch id="layout.shortsplayer.shortsPlayerTypePatch">
|
||||
<string name="revanced_shorts_player_type_title">ŲØĒØ Ų
ŲØ§ØˇØš اŲŲShorts Ø¨Ø§ØŗØĒ؎داŲ
</string>
|
||||
<string name="revanced_shorts_player_type_shorts">Ų
Ø´ØēŲ Shorts</string>
|
||||
<string name="revanced_shorts_player_type_regular_player">Ų
Ø´ØēŲ ØšØ§Ø¯Ų</string>
|
||||
<string name="revanced_shorts_player_type_regular_player_fullscreen">شاش؊ ŲØ§Ų
ŲØŠ - Ų
Ø´ØēŲ ØšØ§Ø¯Ų</string>
|
||||
</patch>
|
||||
<patch id="layout.shortsautoplay.shortsAutoplayPatch">
|
||||
<string name="revanced_shorts_autoplay_title">Ø§ŲØĒØ´ØēŲŲ Ø§ŲØĒŲŲØ§ØĻŲ ŲŲŲØ¯ŲŲŲØ§ØĒ Shorts</string>
|
||||
<string name="revanced_shorts_autoplay_summary_on">ØŗŲØĒŲ
ØĒØ´ØēŲŲ ŲŲØ¯ŲŲŲØ§ØĒ Shorts ØĒŲŲØ§ØĻŲŲØ§</string>
|
||||
@@ -1280,22 +1286,13 @@ Second \"item\" text"</string>
|
||||
|
||||
ŲØ¯ ŲØ§ ŲØšŲ
Ų ØĒØ´ØēŲŲ Ø§ŲŲŲØ¯ŲŲ"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">ØĨŲŲØ§Ų ØĒØ´ØēŲŲ ŲØ°Ø§ Ø§ŲØĨؚداد ŲØ¯ ŲØŗØ¨Ø¨ Ų
شاŲŲ ŲŲ ØĒØ´ØēŲŲ Ø§ŲŲŲØ¯ŲŲ.</string>
|
||||
<string name="revanced_spoof_video_streams_client_title">Ø§ŲØšŲ
ŲŲ Ø§ŲØ§ŲØĒØąØ§ØļŲ</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">ŲØąØļ AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">ØĒŲ
ŲØąØļ ØĒØąŲ
ŲØ˛ اŲŲŲØ¯ŲŲ ØšŲŲ AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">ŲØĒŲ
ØĒØØ¯Ųد ØĒØąŲ
ŲØ˛ اŲŲŲØ¯ŲŲ ØĒŲŲØ§ØĻŲŲØ§</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"ŲØ¯ ŲØ¤Ø¯Ų ØĒŲ
ŲŲŲ ŲØ°Ø§ ØĨŲŲ ØĒØØŗŲŲ ØšŲ
Øą Ø§ŲØ¨ØˇØ§ØąŲØŠ ŲØĨØĩŲØ§Ø Ų
Ø´ŲŲØŠ ØĒŲØˇŲØš Ø§ŲØĒØ´ØēŲŲ.
|
||||
|
||||
ŲØĒŲ
ØĒØš ØĒŲØŗŲŲ 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">"âĸ ŲØ¯ ŲØ§ ŲØĒŲ
ØĒØ´ØēŲŲ ŲŲØ¯ŲŲŲØ§ØĒ Ø§ŲØŖØˇŲاŲ
|
||||
âĸ ØĒØ¨Ø¯ØŖ Ø§ŲØ¨ØĢŲØĢ Ø§ŲŲ
Ø¨Ø§Ø´ØąØŠ Ų
Ų Ø§ŲØ¨Ø¯Ø§ŲØŠ
|
||||
âĸ ŲØ¯ ØĒŲØĒŲŲ Ø§ŲŲŲØ¯ŲŲŲØ§ØĒ ŲØ¨Ų اŲŲŲØ§ŲØŠ بØĢاŲŲØŠ ŲØ§ØØ¯ØŠ"</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">Ø§ŲØšŲ
ŲŲ Ø§ŲØ§ŲØĒØąØ§ØļŲ</string>
|
||||
<string name="revanced_spoof_video_streams_about_title">ØĸØĢØ§Øą ØŦØ§ŲØ¨ŲØŠ ŲŲŲ
ŲØŠ</string>
|
||||
<string name="revanced_spoof_video_streams_about_summary">"âĸ اŲŲØ§ØĻŲ
ØŠ Ø§ŲØĩŲØĒŲØŠ Ų
ŲŲŲØ¯ØŠ
|
||||
âĸ Ø§ŲØĩŲØĒ Ø§ŲØĢØ§Ø¨ØĒ ØēŲØą Ų
ØĒŲŲØą
|
||||
âĸ ŲØąØļ Ø§ŲØĩŲØĒ Ø§ŲØŖØĩŲŲ ØēŲØą Ų
ØĒŲŲØą"</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">ŲØēØŠ Ø§ŲØ¨ØĢ Ø§ŲØĩŲØĒŲ Ø§ŲØ§ŲØĒØąØ§ØļŲØŠ</string>
|
||||
<string name="revanced_spoof_video_streams_language_DEFAULT">ŲØēØŠ Ø§ŲØĒØˇØ¨ŲŲ</string>
|
||||
<string name="revanced_spoof_video_streams_language_DEFAULT">ŲØēØŠ Ø§ŲØØŗØ§Ø¨</string>
|
||||
<string name="revanced_spoof_video_streams_language_AR">Ø§ŲØšØąØ¨ŲØŠ</string>
|
||||
<string name="revanced_spoof_video_streams_language_AZ">Azerbaijani</string>
|
||||
<string name="revanced_spoof_video_streams_language_BG">Bulgarian</string>
|
||||
@@ -1331,8 +1328,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_spoof_video_streams_language_OR">Odia</string>
|
||||
<string name="revanced_spoof_video_streams_language_PA">Punjabi</string>
|
||||
<string name="revanced_spoof_video_streams_language_PL">Polish</string>
|
||||
<string name="revanced_spoof_video_streams_language_PT_BR">Portuguese (Brazil)</string>
|
||||
<string name="revanced_spoof_video_streams_language_PT_PT">Portuguese (Portugal)</string>
|
||||
<string name="revanced_spoof_video_streams_language_RO">Romanian</string>
|
||||
<string name="revanced_spoof_video_streams_language_RU">Russian</string>
|
||||
<string name="revanced_spoof_video_streams_language_SK">Slovak</string>
|
||||
|
||||
@@ -164,6 +164,8 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.startupshortsreset.disableResumingShortsOnStartupPatch">
|
||||
</patch>
|
||||
<patch id="layout.shortsplayer.shortsPlayerTypePatch">
|
||||
</patch>
|
||||
<patch id="layout.shortsautoplay.shortsAutoplayPatch">
|
||||
</patch>
|
||||
<patch id="layout.tablet.enableTabletLayoutPatch">
|
||||
|
||||
@@ -24,13 +24,13 @@ Second \"item\" text"</string>
|
||||
<patch id="misc.checks.checkEnvironmentPatch">
|
||||
<string name="revanced_check_environment_failed_title">Yoxlamalar uÄursuz oldu</string>
|
||||
<string name="revanced_check_environment_dialog_open_official_source_button">XidmÉti veb saytÄą aç</string>
|
||||
<string name="revanced_check_environment_dialog_ignore_button">Yan keç</string>
|
||||
<string name="revanced_check_environment_failed_message"><h5>Bu tÉtbiq sizin tÉrÉfinizdÉn yamaqlanmayÄąb.</h5><br>Bu tÉtbiq dÃŧzgÃŧn iÅlÉmÉyÉ bilÉr, <b>istifadÉ etmÉk zÉrÉrli vÉ ya hÉtta tÉhlÃŧkÉli ola bilÉr</b>.<br><br>Bu yoxlamalar bu tÉtbiqin ÉvvÉldÉn yamaqlandÄąÄÄąnÄą vÉ ya baÅqasÄąndan ÉldÉ edildiyini gÃļstÉrir:<br><br><small>%1$s</small><br> <br>onu silmÉyiniz vÉ ÃļzÃŧnÃŧz yamaqlamaÄÄąnÄąz tÃļvsiyÉ olunur. </b>tÉsdiqlÉnmiÅ vÉ tÉhlÃŧkÉsiz tÉtbiq istifadÉ etdiyinizÉ Émin olmaq ÃŧçÃŧn. <p><br> İnkar edilmÉzsÉ, bu xÉbÉrdarlÄąq yalnÄąz iki dÉfÉ gÃļstÉrilÉcÉk.</string>
|
||||
<string name="revanced_check_environment_dialog_ignore_button">MÉhÉl qoyma</string>
|
||||
<string name="revanced_check_environment_failed_message"><h5>Bu tÉtbiq sizin tÉrÉfinizdÉn yamaqlanmayÄąb.</h5><br>Bu tÉtbiq dÃŧzgÃŧn iÅlÉmÉyÉ bilÉr, <b>istifadÉ etmÉk zÉrÉrli vÉ ya hÉtta tÉhlÃŧkÉli ola bilÉr</b>.<br><br>Bu yoxlamalar bu tÉtbiqin ÉvvÉl yamaqlandÄąÄÄąnÄą vÉ ya baÅqasÄąndan ÉldÉ edildiyini bildirir:<br><br><small>%1$s</small><br> <br>onu silmÉyiniz vÉ ÃļzÃŧnÃŧz yamaqlamaÄÄąnÄąz tÃļvsiyÉ olunur. </b>tÉsdiqlÉnmiÅ vÉ tÉhlÃŧkÉsiz tÉtbiq istifadÉ etdiyinizÉ Émin olmaq ÃŧçÃŧn. <p><br> LÉÄv edilmÉzsÉ, bu xÉbÉrdarlÄąq yalnÄąz iki dÉfÉ gÃļstÉrilÉcÉk.</string>
|
||||
<string name="revanced_check_environment_not_same_patching_device">FÉrqli cihazda yamaqlanÄąb</string>
|
||||
<string name="revanced_check_environment_manager_not_expected_installer">ReVanced Manager tÉrÉfindÉn quraÅdÄąrÄąlmayÄąb</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time">10 dÉqiqÉdÉn çox ÉvvÉl yamaqlanÄąb</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time_days">%s gÃŧn ÉvvÉl yamaqlanÄąb</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time_invalid">APK quruluÅ tarixi pozulub</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time_invalid">APK qurulma vaxtÄą pozulub</string>
|
||||
</patch>
|
||||
<patch id="misc.settings.settingsResourcePatch">
|
||||
<string name="revanced_settings_title">\"ReVanced\"</string>
|
||||
@@ -57,17 +57,17 @@ 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. -->
|
||||
<string name="gms_core_toast_not_installed_message">MicroG GmsCore quraÅdÄąrÄąlmayÄąb. Bunu quraÅdÄąr.</string>
|
||||
<string name="gms_core_dialog_title">FÉaliyyÉt lazÄąmdÄąr</string>
|
||||
<string name="gms_core_dialog_not_whitelisted_not_allowed_in_background_message">"MicroG GmsCore-un arxaplanda iÅlÉmÉsi ÃŧçÃŧn icazÉsi yoxdur.
|
||||
<string name="gms_core_dialog_not_whitelisted_not_allowed_in_background_message">"MicroG GmsCore-un arxa planda iÅlÉmÉsi ÃŧçÃŧn icazÉsi yoxdur.
|
||||
|
||||
Telefonunuz ÃŧçÃŧn \"TÉtbiqimi ÃļldÃŧrmÉ\" bÉlÉdçisinÉ ÉmÉl edin vÉ tÉlimatlarÄą MicroG quraÅdÄąrmanÄąza tÉtbiq edin.
|
||||
Telefonunuz ÃŧçÃŧn \"TÉtbiqimi dayandÄąrma\" bÉlÉdçisinÉ ÉmÉl edin vÉ tÉlimatlarÄą MicroG quraÅdÄąrmanÄąza tÉtbiq edin.
|
||||
|
||||
Bu, tÉtbiqin iÅlÉmÉsi ÃŧçÃŧn tÉlÉb olunur."</string>
|
||||
<string name="gms_core_dialog_open_website_text">Veb saytÄą aç</string>
|
||||
<string name="gms_core_dialog_not_whitelisted_using_battery_optimizations_message">"Problemsiz iÅlÉmÉsi ÃŧçÃŧn MicroG GmsCore batareya optimallaÅdÄąrmalarÄą sÄąradan Ã§ÄąxarÄąlmalÄądÄąr.
|
||||
<string name="gms_core_dialog_not_whitelisted_using_battery_optimizations_message">"ProblemlÉrin olmamasÄą ÃŧçÃŧn MicroG GmsCore batareya optimallaÅmasÄą qapadÄąlmalÄądÄąr.
|
||||
|
||||
MicroG ÃŧçÃŧn batareya optimallaÅdÄąrmasÄąnÄą sÄąradan Ã§Äąxartmaq, batareya istifadÉsinÉ mÉnfi tÉsir etmÉyÉcÉk.
|
||||
MicroG ÃŧçÃŧn batareya optimallaÅmasÄąn qapatma batareya istifadÉsinÉ mÉnfi tÉsir etmÉyÉcÉk.
|
||||
|
||||
Davam dÃŧymÉsinÉ toxunun vÉ optimallaÅdÄąrma dÉyiÅikliklÉrinÉ icazÉ verin."</string>
|
||||
Davam et dÃŧymÉsinÉ toxun vÉ optimallaÅdÄąrma dÉyiÅikliklÉrin qÉbul et."</string>
|
||||
<string name="gms_core_dialog_continue_text">Davam et</string>
|
||||
</patch>
|
||||
</app>
|
||||
@@ -82,10 +82,10 @@ Davam dÃŧymÉsinÉ toxunun vÉ optimallaÅdÄąrma dÉyiÅikliklÉrinÉ icazÉ ver
|
||||
<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>
|
||||
<string name="revanced_shorts_disable_background_playback_title">Shorts arxa plan oynatmasÄąn qapat</string>
|
||||
<string name="revanced_shorts_disable_background_playback_summary_on">Shorts arxa plan oynatma qapalÄądÄąr</string>
|
||||
<string name="revanced_shorts_disable_background_playback_summary_off">Shorts arxa plan oynatma aktivdir</string>
|
||||
</patch>
|
||||
@@ -104,9 +104,9 @@ Davam dÃŧymÉsinÉ toxunun vÉ optimallaÅdÄąrma dÉyiÅikliklÉrinÉ icazÉ ver
|
||||
<string name="revanced_debug_toast_on_error_title">ReVanced xÉtasÄąnda ani bildiriÅ gÃļstÉr</string>
|
||||
<string name="revanced_debug_toast_on_error_summary_on">XÉta baÅ verÉrsÉ bildiriÅ gÃļstÉr</string>
|
||||
<string name="revanced_debug_toast_on_error_summary_off">XÉta baÅ verÉrsÉ bildiriÅ gÃļstÉrmÉ</string>
|
||||
<string name="revanced_debug_toast_on_error_user_dialog_message">"XÉta bildiriÅlÉrini sÃļndÃŧrmÉk, bÃŧtÃŧn ReVanced xÉta bildiriÅlÉrini gizlÉdir.
|
||||
<string name="revanced_debug_toast_on_error_user_dialog_message">"XÉta ani bildiriÅlÉrin qapatmaq, bÃŧtÃŧn ReVanced xÉta bildiriÅlÉrin gizlÉdir.
|
||||
|
||||
GÃļzlÉnilmÉz tÉdbirlÉr barÉdÉ bildiriÅ almayacaqsÄąnÄąz."</string>
|
||||
GÃļzlÉnilmÉz hallardan xÉbÉrdar olmayacaqsÄąnÄąz."</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.general.hideLayoutComponentsPatch">
|
||||
<string name="revanced_disable_like_subscribe_glow_title">BÉyÉn/abunÉ ol dÃŧymÉ parÄąltÄąsÄąn sÃļndÃŧr</string>
|
||||
@@ -125,12 +125,12 @@ GÃļzlÉnilmÉz tÉdbirlÉr barÉdÉ bildiriÅ almayacaqsÄąnÄąz."</string>
|
||||
<string name="revanced_hide_channel_watermark_summary_on">Su niÅanÄą gizlidir</string>
|
||||
<string name="revanced_hide_channel_watermark_summary_off">Su niÅanÄą gÃļstÉrilir</string>
|
||||
<string name="revanced_hide_horizontal_shelves_title">ÃfÃŧqi hissÉlÉri gizlÉt</string>
|
||||
<string name="revanced_hide_horizontal_shelves_summary_on">"RÉflÉr gizlidir, mÉsÉlÉn:
|
||||
<string name="revanced_hide_horizontal_shelves_summary_on">"HissÉlÉr gizlidir, nÃŧmunÉ:
|
||||
âĸ Son xÉbÉrlÉr
|
||||
âĸ İzlÉmÉyÉ davam et
|
||||
âĸ Daha çox kanallar kÉÅf edin
|
||||
âĸ Daha çox kanallar kÉÅf et
|
||||
âĸ AlÄąÅ-veriÅ
|
||||
âĸ YenidÉn izlÉ"</string>
|
||||
âĸ TÉkrar izlÉ"</string>
|
||||
<string name="revanced_hide_horizontal_shelves_summary_off">HissÉlÉr gÃļstÉrilir</string>
|
||||
<!-- 'Join' should be translated using the same localized wording YouTube displays.
|
||||
This appears in the video player for certain videos. -->
|
||||
@@ -204,8 +204,8 @@ GÃļzlÉnilmÉz tÉdbirlÉr barÉdÉ bildiriÅ almayacaqsÄąnÄąz."</string>
|
||||
<string name="revanced_hide_playables_summary_on">OynadÄąlanlar gizlidir</string>
|
||||
<string name="revanced_hide_playables_summary_off">OynadÄąlanlar gÃļstÉrilir</string>
|
||||
<string name="revanced_hide_quick_actions_title">Tam ekranda cÉld fÉaliyyÉtlÉri gizlÉt</string>
|
||||
<string name="revanced_hide_quick_actions_summary_on">SÃŧrÉtli fÉaliyyÉtlÉr gizlÉdilir</string>
|
||||
<string name="revanced_hide_quick_actions_summary_off">SÃŧrÉtli fÉaliyyÉtlÉr gÃļstÉrilir</string>
|
||||
<string name="revanced_hide_quick_actions_summary_on">CÉld fÉaliyyÉtlÉr gizlÉdilir</string>
|
||||
<string name="revanced_hide_quick_actions_summary_off">CÉld fÉaliyyÉtlÉr gÃļstÉrilir</string>
|
||||
<string name="revanced_hide_related_videos_title">CÉld fÉaliyyÉtlÉrdÉ ÉlaqÉli videolarÄą gizlÉ</string>
|
||||
<string name="revanced_hide_related_videos_summary_on">ÆlaqÉdar videolar gizlÉdilib</string>
|
||||
<string name="revanced_hide_related_videos_summary_off">ÆlaqÉdar videolar gÃļstÉrilir</string>
|
||||
@@ -279,11 +279,11 @@ GÃļzlÉnilmÉz tÉdbirlÉr barÉdÉ bildiriÅ almayacaqsÄąnÄąz."</string>
|
||||
<string name="revanced_hide_doodles_title">YouTube Doodle-larÄą gizlÉt</string>
|
||||
<string name="revanced_hide_doodles_summary_on">AxtarÄąÅ Ã§ubuÄu Doodle-larÄą gizlidir</string>
|
||||
<string name="revanced_hide_doodles_summary_off">AxtarÄąÅ Ã§ubuÄu Doodle-larÄą gÃļstÉrilir</string>
|
||||
<string name="revanced_hide_doodles_user_dialog_message">"YouTube Doodles ilinin bir neÃ§É gÃŧnÃŧ gÃļstÉrilir.
|
||||
<string name="revanced_hide_doodles_user_dialog_message">"YouTube Doodle-larÄą hÉr il bir neÃ§É gÃŧn gÃļrÃŧnÃŧr.
|
||||
|
||||
ÆgÉr Doodle hazÄąrda sizin bÃļlgÉnizdÉ gÃļstÉrilirsÉ vÉ bu gizlÉtmÉ parametr aÃ§ÄąqdÄąrsa, axtarÄąÅ Ã§ubuÄunun altÄąndakÄą filtr çubuÄu da gizlÉnÉcÉk."</string>
|
||||
ÆgÉr hazÄąrda bÃļlgÉnizdÉ Doodle gÃļstÉrilirsÉ vÉ bu gizlÉtmÉ seçimi aktivdirsÉ, axtarÄąÅ cizgisi aÅaÄÄąsÄąndakÄą filtr sahÉsi dÉ gizlÉdilÉcÉk."</string>
|
||||
<string name="revanced_custom_filter_screen_title">ÅÉxsi filtr</string>
|
||||
<string name="revanced_custom_filter_screen_summary">FÉrdi filtrlÉr ilÉ elementlÉri gizlÉt</string>
|
||||
<string name="revanced_custom_filter_screen_summary">FÉrdi filtrlÉr iÅlÉdÉrÉk elementlÉri gizlÉt</string>
|
||||
<string name="revanced_custom_filter_title">FÉrdi filtri aktivlÉÅdir</string>
|
||||
<string name="revanced_custom_filter_summary_on">FÉrdi filtr aktivdir</string>
|
||||
<string name="revanced_custom_filter_summary_off">FÉrdi filtr qeyri-aktivdir</string>
|
||||
@@ -305,18 +305,18 @@ GÃļzlÉnilmÉz tÉdbirlÉr barÉdÉ bildiriÅ almayacaqsÄąnÄąz."</string>
|
||||
<string name="revanced_hide_keyword_content_phrases_title">GizlÉdilÉcÉk açar sÃļzlÉr</string>
|
||||
<!-- For localization it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word.
|
||||
This is because keywords can be in any language, and showing an example in the localized script helps convey this. -->
|
||||
<string name="revanced_hide_keyword_content_phrases_summary">"KÉnarda qoyulacaq açar sÃļzlÉr vÉ cÃŧmlÉlÉr, yeni sÉtirlÉrlÉ ayrÄąlmÄąÅdÄąr
|
||||
<string name="revanced_hide_keyword_content_phrases_summary">"Yeni sÉtirlÉrlÉ ayrÄąlan, gizlÉdilÉcÉk açar sÃļzlÉr vÉ ifadÉlÉr
|
||||
|
||||
Açar sÃļzlÉr kanal adlarÄą vÉ ya video baÅlÄąqlarÄąnda gÃļstÉrilÉn hÉr hansÄą mÉtn ola bilÉr.
|
||||
Açar sÃļzlÉr kanal adlarÄą vÉ ya video adlarÄąnda gÃļstÉrilÉn istÉnilÉn mÉtn ola bilÉr.
|
||||
|
||||
Orta hÉrflÉri bÃļyÃŧk hÉrflÉrlÉ olan sÃļzlÉr bÃļyÃŧk hÉrflÉrlÉ yazÄąlmalÄądÄąr (mÉsÉlÉn: iPhone, TikTok, LeBlanc)"</string>
|
||||
Ortada bÃļyÃŧk hÉrflli sÃļzlÉr belÉ yerlÉÅdirilmÉlidir (yÉni: iPhone, TikTok, LeBlanc)"</string>
|
||||
<string name="revanced_hide_keyword_content_about_title">Açar sÃļz filtrlÉmÉsi haqqÄąnda</string>
|
||||
<string name="revanced_hide_keyword_content_about_summary">"Ana sÉhifÉ/AbunÉlik/AxtarÄąÅ nÉticÉlÉri açar sÃļz ifadÉlÉrinÉ uyÄun olan mÉzmunu gizlÉtmÉk ÃŧçÃŧn sÃŧzÃŧlÃŧr
|
||||
<string name="revanced_hide_keyword_content_about_summary">"Ev/AbunÉlik/AxtarÄąÅ nÉticÉlÉri açar sÃļz ifadÉlÉrinÉ uyÄun olan mÉzmunu gizlÉtmÉk ÃŧçÃŧn çeÅidlÉnir
|
||||
|
||||
MÉhdudiyyÉtlÉr
|
||||
âĸ Åortlar kanal adÄą ilÉ gizlÉnÉ bilmÉz
|
||||
âĸ BÉzi UI komponentlÉri gizlÉnÉ bilmÉz
|
||||
âĸ Açar sÃļz axtarmaq heç bir nÉticÉ vermÉyÉ bilÉr"</string>
|
||||
âĸ Shorts-lar kanal adÄą ilÉ gizlÉnÉ bilmÉz
|
||||
âĸ BÉzi UI hissÉciklÉri gizlÉnÉ bilmÉz
|
||||
âĸ Açar sÃļz axtarma nÉticÉ vermÉyÉ bilÉr"</string>
|
||||
<string name="revanced_hide_keyword_content_about_whole_words_title">BÃŧtÃŧn sÃļzlÉri uyÄunlaÅdÄąr</string>
|
||||
<!-- Translations _must_ use a localized example. For languages that do not use spaces between words (Chinese, Japanese, etc) the English AI example should be used since no localized examples exist. Or if using machine translations, or if nobody wants to think of a localized example, then the English 'ai' example should be left as-is. -->
|
||||
<string name="revanced_hide_keyword_content_about_whole_words_summary">Açar sÃļz/frazanÄąn qoÅa dÄąrnaqlarla ÉhatÉ olunmasÄą video adlarÄą vÉ kanal adlarÄąnÄąn qismÉn uyÄunlaÅmasÄąna mane olacaq <br><br>MÉsÉlÉn,<br><b>\"ai\"</b> videonu gizlÉdÉcÉk:<b>How does AI work?</b><br> lakin gizlÉtmÉyÉcÉk: DÃŧzgÃŧn;<b>What does fair use mean?</b></string>
|
||||
@@ -332,7 +332,7 @@ MÉhdudiyyÉtlÉr
|
||||
<string name="revanced_hide_general_ads_summary_on">Ãmumi reklamlar gizlidir</string>
|
||||
<string name="revanced_hide_general_ads_summary_off">Ãmumi reklamlar gÃļstÉrilir</string>
|
||||
<string name="revanced_hide_fullscreen_ads_title">Tam ekran reklamlarÄąnÄą gizlÉt</string>
|
||||
<string name="revanced_hide_fullscreen_ads_summary_on">"Tam ekran reklam gizlidir
|
||||
<string name="revanced_hide_fullscreen_ads_summary_on">"Tam ekran reklamlarÄą gizlidir
|
||||
|
||||
Bu xÃŧsusiyyÉt yalnÄąz kÃļhnÉ cihazlar ÃŧçÃŧn mÃļvcuddur"</string>
|
||||
<string name="revanced_hide_fullscreen_ads_summary_off">Tam ekran reklamlarÄą gÃļstÉrilir</string>
|
||||
@@ -348,14 +348,14 @@ Bu xÃŧsusiyyÉt yalnÄąz kÃļhnÉ cihazlar ÃŧçÃŧn mÃļvcuddur"</string>
|
||||
<string name="revanced_hide_products_banner_title">MÉhsullara baxma etiketin gizlÉt</string>
|
||||
<string name="revanced_hide_products_banner_summary_on">Etiket gizlÉdilib</string>
|
||||
<string name="revanced_hide_products_banner_summary_off">Etiket gÃļstÉrilir</string>
|
||||
<string name="revanced_hide_player_store_shelf_title">OynadÄącÄą alÄąÅ-veriÅ rÉfini gizlÉt</string>
|
||||
<string name="revanced_hide_player_store_shelf_title">OynadÄącÄą alÄąÅ-veriÅ bÃļlmÉsin gizlÉt</string>
|
||||
<string name="revanced_hide_player_store_shelf_summary_on">AlÄąÅ-veriÅ rÉfi gizlidir</string>
|
||||
<string name="revanced_hide_player_store_shelf_summary_off">AlÄąÅ-veriÅ rÉfi gÃļstÉrilir</string>
|
||||
<string name="revanced_hide_shopping_links_title">Video aÃ§Äąqlama alÄąÅ-veriÅ linklÉr gizlÉ</string>
|
||||
<string name="revanced_hide_shopping_links_title">Video aÃ§Äąqlamada alÄąÅ-veriÅ linklÉrin gizlÉ</string>
|
||||
<string name="revanced_hide_shopping_links_summary_on">AlÄąÅ-veriÅ baÄlantÄąlarÄą gizlÉdilir</string>
|
||||
<string name="revanced_hide_shopping_links_summary_off">AlÄąÅ-veriÅ baÄlantÄąlarÄą gÃļstÉrilir</string>
|
||||
<!-- 'Visit store' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_visit_store_button_title">Kanalda \"MaÄaza ziyarÉt\" dÃŧymÉ gizlÉ</string>
|
||||
<string name="revanced_hide_visit_store_button_title">Kanalda \"MaÄazaya ziyarÉt\" dÃŧymÉsin gizlÉ</string>
|
||||
<string name="revanced_hide_visit_store_button_summary_on">DÃŧymÉ gizlidir</string>
|
||||
<string name="revanced_hide_visit_store_button_summary_off">DÃŧymÉ gÃļstÉrilir</string>
|
||||
<string name="revanced_hide_web_search_results_title">Veb axtarÄąÅ nÉticÉlÉrini gizlÉt</string>
|
||||
@@ -1049,6 +1049,12 @@ Sonradan sÃļndÃŧrÃŧlÉrsÉ, UI sÉhvlÉrini qarÅÄąsÄąnÄą almaq ÃŧçÃŧn tÉtbiqi
|
||||
<string name="revanced_disable_resuming_shorts_player_summary_on">TÉtbiq aÃ§Äąlanda Shorts oynadÄącÄą davam etmÉyÉcÉk</string>
|
||||
<string name="revanced_disable_resuming_shorts_player_summary_off">TÉtbiq aÃ§Äąlanda Shorts oynadÄącÄą davam edÉcÉk</string>
|
||||
</patch>
|
||||
<patch id="layout.shortsplayer.shortsPlayerTypePatch">
|
||||
<string name="revanced_shorts_player_type_title">Shorts ilÉ</string>
|
||||
<string name="revanced_shorts_player_type_shorts">Shorts oynadÄącÄą</string>
|
||||
<string name="revanced_shorts_player_type_regular_player">Adi oynatÄącÄą</string>
|
||||
<string name="revanced_shorts_player_type_regular_player_fullscreen">Adi oynatÄącÄą tam ekran</string>
|
||||
</patch>
|
||||
<patch id="layout.shortsautoplay.shortsAutoplayPatch">
|
||||
<string name="revanced_shorts_autoplay_title">Shorts-larÄą avto-oynatma</string>
|
||||
<string name="revanced_shorts_autoplay_summary_on">Shorts-lar avto-oynadÄąlacaq</string>
|
||||
@@ -1281,20 +1287,11 @@ Bunu aktivlÉÅdirmÉ daha yÃŧksÉk video keyfiyyÉtlÉri ÉngÉlin silÉ bilÉr
|
||||
|
||||
Video oynatma iÅlÉmÉyÉ bilÉr"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">Bu seçimi baÄlamaq, video oynatma problemlÉrinÉ sÉbÉb olar.</string>
|
||||
<string name="revanced_spoof_video_streams_client_title">İlkin qÉbuledici</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">MÉcburi AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">Video kodlama AVC (H.264) -yÉ mÉcbur edilir</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">Video kodlama birbaÅa yoxlanÄąlÄąr</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"Bunu fÉallaÅdÄąrma, batareya ÃļmrÃŧnÃŧ yaxÅÄąlaÅdÄąra vÉ oxutma iliÅmÉlÉrini dÃŧzÉldÉ bilÉr.
|
||||
|
||||
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">"âĻ 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
|
||||
âĸ Videolar 1 saniyÉ tez bitir"</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">İlkin qÉbuledici</string>
|
||||
<string name="revanced_spoof_video_streams_about_title">Yan effektlÉrin spoof edilmÉsi</string>
|
||||
<string name="revanced_spoof_video_streams_about_summary">"âĸ SÉs parçasÄą menyusunda sÉhvlÉr var
|
||||
âĸ Sabit sÉs sÉviyyÉsi mÃļvcud deyil
|
||||
âĸ MÉcburi orijinal sÉs mÃļvcud deyil"</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">İlkin sÉs yayÄąmÄą dili</string>
|
||||
<string name="revanced_spoof_video_streams_language_DEFAULT">TÉtbiq dili</string>
|
||||
<string name="revanced_spoof_video_streams_language_AR">ÆrÉbcÉ</string>
|
||||
@@ -1332,8 +1329,6 @@ AVC-nin maksimum dÉqiqliyi 1080p-dir, Opus sÉs kodek Élçatan deyil vÉ video
|
||||
<string name="revanced_spoof_video_streams_language_OR">Oriya dili</string>
|
||||
<string name="revanced_spoof_video_streams_language_PA">PÉncabca</string>
|
||||
<string name="revanced_spoof_video_streams_language_PL">Polyak dili</string>
|
||||
<string name="revanced_spoof_video_streams_language_PT_BR">Portuqalca (Braziliya)</string>
|
||||
<string name="revanced_spoof_video_streams_language_PT_PT">Portuqalca (PortÉgiz)</string>
|
||||
<string name="revanced_spoof_video_streams_language_RO">RumÄąnca</string>
|
||||
<string name="revanced_spoof_video_streams_language_RU">Rusca</string>
|
||||
<string name="revanced_spoof_video_streams_language_SK">Slovak dili</string>
|
||||
|
||||
@@ -668,8 +668,8 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_shorts_use_template_button_summary_on">ĐĐŊĐžĐŋĐēа вŅĐēаŅŅŅŅаĐŊĐŊŅ ŅайĐģĐžĐŊŅ ŅŅ
аваĐŊа</string>
|
||||
<string name="revanced_hide_shorts_use_template_button_summary_off">ĐĐŊĐžĐŋĐēа вŅĐēаŅŅŅŅаĐŊĐŊŅ ŅайĐģĐžĐŊŅ ĐŋаĐēаСаĐŊа</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_title">ĐĄŅ
аваŅŅ ĐēĐŊĐžĐŋĐēŅ ĐąŅĐ´ŅŅŅŅ
</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_summary_on">ĐĐŊĐžĐŋĐēа âŦī¸ĐŅĐ´ŅŅиĐĩ ŅĐžĐģиĐēиâŦī¸ ŅĐēŅŅŅа</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_summary_off">ĐĐŊĐžĐŋĐēа âŦī¸ĐŅĐ´ŅŅиĐĩ ŅĐžĐģиĐēиâŦī¸ ĐžŅОйŅаĐļаĐĩŅŅŅ</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_summary_on">ĐĐŊĐžĐŋĐēа ĐŅĐ´ŅŅиĐĩ ŅĐžĐģиĐēи ŅĐēŅŅŅа</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_summary_off">ĐĐŊĐžĐŋĐēа ĐŅĐ´ŅŅиĐĩ ŅĐžĐģиĐēи ĐžŅОйŅаĐļаĐĩŅŅŅ</string>
|
||||
<string name="revanced_hide_shorts_green_screen_button_title">ĐĄĐēŅŅŅŅ ĐēĐŊĐžĐŋĐēŅ Ņ ĐˇĐĩĐģŅĐŊŅĐŧ ŅĐēŅаĐŊĐžĐŧ Shorts</string>
|
||||
<string name="revanced_hide_shorts_green_screen_button_summary_on">ĐĐŊĐžĐŋĐēа Ņ ĐˇĐĩĐģŅĐŊŅĐŧ ŅĐēŅаĐŊĐžĐŧ Shorts ŅĐēŅŅŅа</string>
|
||||
<string name="revanced_hide_shorts_green_screen_button_summary_off">ĐĐŊĐžĐŋĐēа Ņ ĐˇĐĩĐģŅĐŊŅĐŧ ŅĐēŅаĐŊĐžĐŧ Shorts ĐžŅОйŅаĐļаĐĩŅŅŅ</string>
|
||||
@@ -1051,6 +1051,12 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_disable_resuming_shorts_player_summary_on">ĐŅĐ°ĐšĐŗŅаваĐģŅĐŊŅĐē Shorts ĐŊĐĩ адĐŊаŅĐģŅĐĩŅŅа ĐŋŅŅ ĐˇĐ°ĐŋŅŅĐēŅ ĐŋŅĐ°ĐŗŅаĐŧŅ</string>
|
||||
<string name="revanced_disable_resuming_shorts_player_summary_off">ĐŅĐ°ĐšĐŗŅаваĐģŅĐŊŅĐē Shorts адĐŊОвŅŅŅа ĐŋŅŅ ĐˇĐ°ĐŋŅŅĐēŅ ĐŋŅĐ°ĐŗŅаĐŧŅ</string>
|
||||
</patch>
|
||||
<patch id="layout.shortsplayer.shortsPlayerTypePatch">
|
||||
<string name="revanced_shorts_player_type_title">ĐĐ´ĐēŅŅŅŅ Shorts С</string>
|
||||
<string name="revanced_shorts_player_type_shorts">ĐŅĐ°ĐšĐŗŅаваĐģŅĐŊŅĐē Shorts</string>
|
||||
<string name="revanced_shorts_player_type_regular_player">ĐвŅŅаКĐŊŅ ĐŋŅĐ°ĐšĐŗŅаваĐģŅĐŊŅĐē</string>
|
||||
<string name="revanced_shorts_player_type_regular_player_fullscreen">ĐвŅŅаКĐŊŅ ĐŋŅĐ°ĐšĐŗŅаваĐģŅĐŊŅĐē ĐŊа ŅвĐĩŅŅ ŅĐēŅаĐŊ</string>
|
||||
</patch>
|
||||
<patch id="layout.shortsautoplay.shortsAutoplayPatch">
|
||||
<string name="revanced_shorts_autoplay_title">ĐвŅОвОŅĐŋŅОиСвĐĩĐ´ĐĩĐŊиĐĩ Shorts</string>
|
||||
<string name="revanced_shorts_autoplay_summary_on">Shorts ĐąŅĐ´ŅŅ Đ˛ĐžŅĐŋŅОиСвОдиŅŅŅŅ Đ°Đ˛ŅĐžĐŧаŅиŅĐĩŅĐēи</string>
|
||||
@@ -1282,22 +1288,12 @@ Second \"item\" text"</string>
|
||||
|
||||
ĐŅĐ°ĐšĐŗŅаваĐŊĐŊĐĩ вŅĐ´Ņа ĐŧĐžĐļа ĐŊĐĩ ĐŋŅаŅаваŅŅ"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">ĐĐ´ĐēĐģŅŅŅĐŊĐŊĐĩ ĐŗŅŅаК ĐŊаĐģĐ°Đ´Ņ ĐŧĐžĐļа вŅĐēĐģŅĐēаŅŅ ĐŋŅайĐģĐĩĐŧŅ Đˇ ĐŋŅĐ°ĐšĐŗŅаваĐŊĐŊĐĩĐŧ вŅĐ´Ņа.</string>
|
||||
<string name="revanced_spoof_video_streams_client_title">ĐĐģиĐĩĐŊŅ ĐŋĐž ŅĐŧĐžĐģŅаĐŊиŅ</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">ĐŅиĐŊŅдиŅĐĩĐģŅĐŊĐž AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">ĐидĐĩĐžĐēОдĐĩĐē ĐŋŅиĐŊŅдиŅĐĩĐģŅĐŊĐž ŅŅŅаĐŊОвĐģĐĩĐŊ в AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">ĐидĐĩĐžĐēОдĐĩĐē ĐžĐŋŅĐĩĐ´ĐĩĐģŅĐĩŅŅŅ Đ°Đ˛ŅĐžĐŧаŅиŅĐĩŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"ĐŖĐēĐģŅŅŅĐŊĐŊĐĩ ĐŗŅŅĐ°ĐŗĐ° ĐŧĐžĐļа ĐŋаĐģĐĩĐŋŅŅŅŅ ŅŅŅĐŧŅĐŊ ŅĐģŅĐļĐąŅ ĐąĐ°ŅаŅŅŅ Ņ Đ˛ŅĐŋŅавŅŅŅ ĐˇĐ°ŅĐēаĐŊĐŊĐĩ вŅĐ´Ņа.
|
||||
|
||||
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">"âĸ ĐСŅŅŅŅŅŅ Đ˛ŅĐ´Ņа ĐŧĐžĐŗŅŅŅ ĐŊĐĩ ĐŋŅĐ°ĐšĐŗŅаваŅŅа
|
||||
âĸ ĐĸŅаĐŊŅĐģŅŅŅŅ Ņ ĐŋŅаĐŧŅĐŧ ŅŅŅŅŅ ĐŋаŅŅĐŊаŅŅŅа С ĐŋаŅаŅĐēŅ
|
||||
âĸ ĐŅĐ´Ņа СаĐēаĐŊŅваŅŅŅа ĐŊа 1 ŅĐĩĐēŅĐŊĐ´Ņ ŅаĐŊĐĩĐš"</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">ĐĐģиĐĩĐŊŅ ĐŋĐž ŅĐŧĐžĐģŅаĐŊиŅ</string>
|
||||
<string name="revanced_spoof_video_streams_about_title">ĐадŅОйĐēа ĐŋайОŅĐŊŅŅ
ŅŅĐĩĐēŅаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_about_summary">"âĸ ĐŅĐ´ŅŅдаŅĐžĐļĐēŅ, ĐŋаСĐŊаŅаĐŊŅŅ ŅĐē аŅŅĐŗŅĐŊаĐģŅĐŊŅŅ, ĐŧĐžĐŗŅŅŅ ĐąŅŅŅ ĐˇĐŧĐĩĐŊĐĩĐŊŅ ĐŊа ŅĐŊŅŅŅ
|
||||
âĸ ФŅĐŊĐēŅŅŅ \"ĐĄŅайŅĐģŅĐŊĐ°Ņ ĐŗŅŅĐŊаŅŅŅ\" ĐŊĐĩдаŅŅŅĐŋĐŊаŅ"</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">Đ¯ĐˇŅĐē ĐŋĐžŅĐžĐēа аŅдиО ĐŋĐž ŅĐŧĐžĐģŅаĐŊиŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_DEFAULT">Đ¯ĐˇŅĐē ĐŋŅиĐģĐžĐļĐĩĐŊиŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_DEFAULT">ĐОва аĐēаŅĐŊŅа</string>
|
||||
<string name="revanced_spoof_video_streams_language_AR">ĐŅайŅĐēиК</string>
|
||||
<string name="revanced_spoof_video_streams_language_AZ">ĐСĐĩŅйаКдĐļаĐŊŅĐēиК</string>
|
||||
<string name="revanced_spoof_video_streams_language_BG">ĐĐžĐģĐŗĐ°ŅŅĐēиК</string>
|
||||
@@ -1333,8 +1329,6 @@ AVC ĐŧаĐĩ ĐŧаĐēŅŅĐŧаĐģŅĐŊŅŅ ŅаСдСŅĐģŅĐģŅĐŊаŅŅŅ 1080p, аŅĐ´
|
||||
<string name="revanced_spoof_video_streams_language_OR">ĐŅŅŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_PA">ĐаĐŊĐ´ĐļайŅĐēиК</string>
|
||||
<string name="revanced_spoof_video_streams_language_PL">ĐĐžĐģŅŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_PT_BR">ĐаŅŅŅĐŗĐ°ĐģŅŅĐēĐ°Ņ (ĐŅаСŅĐģŅŅ)</string>
|
||||
<string name="revanced_spoof_video_streams_language_PT_PT">ĐаŅŅŅĐŗĐ°ĐģŅŅĐēĐ°Ņ (ĐаŅŅŅĐŗĐ°ĐģŅŅ)</string>
|
||||
<string name="revanced_spoof_video_streams_language_RO">Đ ŅĐŧŅĐŊŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_RU">Đ ŅŅŅĐēаŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_SK">ĐĄĐģОваŅĐēиŅ</string>
|
||||
|
||||
@@ -1049,6 +1049,12 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_disable_resuming_shorts_player_summary_on">Shorts ĐŋĐģĐĩĐšŅŅа ĐŋŅи ŅŅаŅŅиŅаĐŊĐĩ ĐŊа ĐŋŅиĐģĐžĐļĐĩĐŊиĐĩŅĐž Đĩ ŅĐēŅиŅ</string>
|
||||
<string name="revanced_disable_resuming_shorts_player_summary_off">Shorts ĐŋĐģĐĩĐšŅŅа ĐŋŅи ŅŅаŅŅиŅаĐŊĐĩ ĐŊа ĐŋŅиĐģĐžĐļĐĩĐŊиĐĩŅĐž ŅĐĩ ĐŋĐžĐēаСва</string>
|
||||
</patch>
|
||||
<patch id="layout.shortsplayer.shortsPlayerTypePatch">
|
||||
<string name="revanced_shorts_player_type_title">ĐŅвОŅĐĩŅĐĩ Shorts Ņ</string>
|
||||
<string name="revanced_shorts_player_type_shorts">ĐĐŗŅĐ°Ņ ĐŊа Shorts</string>
|
||||
<string name="revanced_shorts_player_type_regular_player">ĐйиĐēĐŊОвĐĩĐŊ ĐŋĐģĐĩĐšŅŅ</string>
|
||||
<string name="revanced_shorts_player_type_regular_player_fullscreen">ĐйиĐēĐŊОвĐĩĐŊ ĐŋĐģĐĩĐšŅŅ ĐŊа ŅŅĐģ ĐĩĐēŅаĐŊ</string>
|
||||
</patch>
|
||||
<patch id="layout.shortsautoplay.shortsAutoplayPatch">
|
||||
<string name="revanced_shorts_autoplay_title">ĐвŅĐžĐŧаŅиŅĐŊĐž ĐŋŅŅĐēаĐŊĐĩ Shorts</string>
|
||||
<string name="revanced_shorts_autoplay_summary_on">Shorts ŅĐĩ ŅĐĩ ĐŋŅŅĐēĐ°Ņ Đ°Đ˛ŅĐžĐŧаŅиŅĐŊĐž</string>
|
||||
@@ -1280,20 +1286,11 @@ Second \"item\" text"</string>
|
||||
|
||||
ĐŅСĐŋŅОиСвĐĩĐļдаĐŊĐĩŅĐž ĐŊа видĐĩĐžĐēĐģиĐŋОвĐĩ ĐŧĐžĐļĐĩ да ĐŊĐĩ ŅайОŅи"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">ĐĐĩаĐēŅивиŅаĐŊĐĩŅĐž ĐŊа ŅаСи ĐŊаŅŅŅОКĐēа ŅĐĩ дОвĐĩĐ´Đĩ Đ´Đž ĐŋŅОйĐģĐĩĐŧи Ņ Đ˛ŅСĐŋŅОиСвĐĩĐļдаĐŊĐĩŅĐž ĐŊа видĐĩĐž.</string>
|
||||
<string name="revanced_spoof_video_streams_client_title">ĐĐģиĐĩĐŊŅ ĐŋĐž ĐŋОдŅаСйиŅаĐŊĐĩ</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">ĐŅиĐŊŅдиŅĐĩĐģĐŊĐž AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">ĐидĐĩĐž ĐēОдĐĩĐē ĐŋĐž ĐŋОдŅаСйиŅаĐŊĐĩ AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">ĐидĐĩĐž ĐēОдĐĩĐēŅŅ ŅĐĩ ĐžĐŋŅĐĩĐ´ĐĩĐģŅ Đ°Đ˛ŅĐžĐŧаŅиŅĐŊĐž</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"ĐĐēŅивиŅаĐŊĐĩŅĐž ĐŊа ŅОва ĐŧĐžĐļĐĩ да ĐŋОдОйŅи ĐļивОŅа ĐŊа йаŅĐĩŅиŅŅа и да ĐŋĐžĐŋŅави СаĐĩĐēваĐŊĐĩŅĐž ĐŊа вŅСĐŋŅОиСвĐĩĐļдаĐŊĐĩŅĐž.
|
||||
|
||||
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">"âĸ ĐĐĩŅŅĐēиŅĐĩ видĐĩĐžĐēĐģиĐŋОвĐĩ ĐŧĐžĐļĐĩ да ĐŊĐĩ ŅĐĩ вŅСĐŋŅОиСвĐĩĐļдаŅ
|
||||
âĸ ĐŅĐĩдаваĐŊиŅŅа ĐŊа ĐļивО СаĐŋĐžŅĐ˛Đ°Ņ ĐžŅ ĐŊаŅаĐģĐžŅĐž
|
||||
âĸ ĐидĐĩĐžĐēĐģиĐŋОвĐĩŅĐĩ СавŅŅŅĐ˛Đ°Ņ 1 ŅĐĩĐēŅĐŊда ĐŋĐž-ŅаĐŊĐž"</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">ĐĐģиĐĩĐŊŅ ĐŋĐž ĐŋОдŅаСйиŅаĐŊĐĩ</string>
|
||||
<string name="revanced_spoof_video_streams_about_title">ФаĐģŅиви ŅŅŅаĐŊиŅĐŊи ĐĩŅĐĩĐēŅи</string>
|
||||
<string name="revanced_spoof_video_streams_about_summary">"âĸ ĐиĐŋŅва ĐŧĐĩĐŊŅŅĐž Са аŅдиО СаĐŋиŅ
|
||||
âĸ ĐĐĩ Đĩ ĐŊаĐģиŅĐĩĐŊ ŅŅайиĐģĐĩĐŊ СвŅĐē
|
||||
âĸ ĐŅиĐŊŅдиŅĐĩĐģĐŊĐž ĐžŅĐ¸ĐŗĐ¸ĐŊаĐģĐŊĐž аŅдиО ĐŊĐĩ Đĩ ĐŊаĐģиŅĐŊĐž"</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">ĐСиĐē ĐŋĐž ĐŋОдŅаСйиŅаĐŊĐĩ ĐŊа аŅдиО ĐŋĐžŅĐžĐēа</string>
|
||||
<string name="revanced_spoof_video_streams_language_DEFAULT">ĐСиĐē ĐŊа ĐŋŅиĐģĐžĐļĐĩĐŊиĐĩŅĐž</string>
|
||||
<string name="revanced_spoof_video_streams_language_AR">ĐŅайŅĐēи</string>
|
||||
@@ -1331,8 +1328,6 @@ AVC иĐŧа ĐŧаĐēŅиĐŧаĐģĐŊа ŅаСдĐĩĐģиŅĐĩĐģĐŊа ŅĐŋĐžŅОйĐŊĐžŅŅ Đž
|
||||
<string name="revanced_spoof_video_streams_language_OR">ĐŅиŅ</string>
|
||||
<string name="revanced_spoof_video_streams_language_PA">ĐĐĩĐŊĐ´ĐļайŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_PL">ĐĐžĐģŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_PT_BR">ĐĐžŅŅŅĐŗĐ°ĐģŅĐēи (ĐŅаСиĐģиŅ)</string>
|
||||
<string name="revanced_spoof_video_streams_language_PT_PT">ĐĐžŅŅŅĐŗĐ°ĐģŅĐēи (ĐĐžŅŅŅĐŗĐ°ĐģиŅ)</string>
|
||||
<string name="revanced_spoof_video_streams_language_RO">Đ ŅĐŧŅĐŊŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_RU">Đ ŅŅĐēи</string>
|
||||
<string name="revanced_spoof_video_streams_language_SK">ĐĄĐģОваŅĐēи</string>
|
||||
|
||||
@@ -1050,6 +1050,12 @@ MicroG-āĻāϰ āĻāύā§āϝ āĻŦā§āϝāĻžāĻāĻžāϰāĻŋ āĻ
āĻĒā§āĻāĻŋāĻŽāĻžāĻāĻ
|
||||
<string name="revanced_disable_resuming_shorts_player_summary_on">āĻ
ā§āϝāĻžāĻĒā§āϰ āĻļā§āϰā§āϤ⧠Shorts āĻĒā§āϞā§ā§āĻžāϰ āĻāĻŦāĻžāϰ āĻāϞāĻŦā§ āύāĻž</string>
|
||||
<string name="revanced_disable_resuming_shorts_player_summary_off">āĻ
ā§āϝāĻžāĻĒā§āϰ āĻļā§āϰā§āϤ⧠Shorts āĻĒā§āϞā§ā§āĻžāϰ āĻāĻŦāĻžāϰ āĻāϞāĻŦā§</string>
|
||||
</patch>
|
||||
<patch id="layout.shortsplayer.shortsPlayerTypePatch">
|
||||
<string name="revanced_shorts_player_type_title">Shorts āϏāĻā§āĻā§ āĻā§āϞā§āύ</string>
|
||||
<string name="revanced_shorts_player_type_shorts">Shorts āĻĒā§āϞā§āϝāĻŧāĻžāϰ</string>
|
||||
<string name="revanced_shorts_player_type_regular_player">āύāĻŋāϝāĻŧāĻŽāĻŋāϤ āĻĒā§āϞā§āϝāĻŧāĻžāϰ</string>
|
||||
<string name="revanced_shorts_player_type_regular_player_fullscreen">āύāĻŋāϝāĻŧāĻŽāĻŋāϤ āĻĒā§āϞā§āϝāĻŧāĻžāϰ āĻĒā§āϰā§āĻŖ āĻĒāϰā§āĻĻāĻž</string>
|
||||
</patch>
|
||||
<patch id="layout.shortsautoplay.shortsAutoplayPatch">
|
||||
<string name="revanced_shorts_autoplay_title">āĻ
āĻā§āĻĒā§āϞ⧠Shorts</string>
|
||||
<string name="revanced_shorts_autoplay_summary_on">Shorts āĻ
āĻā§āĻĒā§āϞ⧠āĻšāĻŦā§</string>
|
||||
@@ -1282,19 +1288,11 @@ DeArrow āϏāĻŽā§āĻĒāϰā§āĻā§ āĻāϰāĻ āĻāĻžāύāϤ⧠āĻāĻāĻžāύ⧠āĻ
|
||||
|
||||
āĻāĻŋāĻĄāĻŋāĻ āĻĒā§āϞā§āĻŦā§āϝāĻžāĻ āĻāĻžāĻ āύāĻžāĻ āĻāϰāϤ⧠āĻĒāĻžāϰā§"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">āĻāĻ āϏā§āĻāĻŋāĻāĻāĻŋ āĻŦāύā§āϧ āĻāϰāĻžāϰ āĻĢāϞ⧠āĻāĻŋāĻĄāĻŋāĻ āĻĒā§āϞā§āĻŦā§āϝāĻžāĻ āϤā§āϰā§āĻāĻŋ āĻšāϤ⧠āĻĒāĻžāϰā§āĨ¤</string>
|
||||
<string name="revanced_spoof_video_streams_client_title">āĻĄāĻŋāĻĢāϞā§āĻ āĻā§āϞāĻžā§ā§āύā§āĻ</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">AVC (H.264) āĻĢā§āϰā§āϏ āĻāϰā§āύ</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">āĻāĻŋāĻĄāĻŋāĻ āĻā§āĻĄā§āĻ AVC (H.264) āϤ⧠āĻŦāĻžāϧā§āϝ āĻāϰāĻž āĻšāϝāĻŧā§āĻā§</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">āĻāĻŋāĻĄāĻŋāĻ āĻā§āĻĄā§āĻ āϏā§āĻŦāϝāĻŧāĻāĻā§āϰāĻŋāϝāĻŧāĻāĻžāĻŦā§ āύāĻŋāϰā§āϧāĻžāϰāĻŋāϤ āĻšāĻā§āĻā§</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"āĻāĻāĻŋ āϏāĻā§āϰāĻŋāϝāĻŧ āĻāϰāĻž āĻŦā§āϝāĻžāĻāĻžāϰāĻŋ āϞāĻžāĻāĻĢ āĻāύā§āύāϤ āĻāϰāϤ⧠āĻĒāĻžāϰ⧠āĻāĻŦāĻ āĻĒā§āϞā§āĻŦā§āϝāĻžāĻ āĻšā§āĻāĻāĻ āĻāĻžāĻāϝāĻŧāĻž āĻ āĻŋāĻ āĻāϰāϤ⧠āĻĒāĻžāϰā§āĨ¤
|
||||
|
||||
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">"âĸ āĻŦā§āϏāϰāĻāĻžāϰāĻŋ āĻļāĻŋāĻļā§ āĻāĻŋāĻĄāĻŋāĻ āĻāϞāϤ⧠āύāĻžāĻ āĻĒāĻžāϰā§<br>âĸ āĻāĻŋāĻĄāĻŋāĻāĻā§āϞāĻŋ 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">"âĸ āĻļāĻŋāĻļā§ āĻāĻŋāĻĄāĻŋāĻāĻā§āϞāĻŋ āĻĒā§āϞ⧠āύāĻžāĻ āĻšāϤ⧠āĻĒāĻžāϰā§
|
||||
âĸ āϞāĻžāĻāĻāϏā§āĻā§āϰāĻŋāĻŽ āĻļā§āϰ⧠āĻĨā§āĻā§ āĻļā§āϰ⧠āĻšāϝāĻŧ
|
||||
âĸ āĻāĻŋāĻĄāĻŋāĻ 1 āϏā§āĻā§āύā§āĻĄ āĻāĻā§ āĻļā§āώ āĻšāϝāĻŧ"</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">āĻĄāĻŋāĻĢāϞā§āĻ āĻā§āϞāĻžā§ā§āύā§āĻ</string>
|
||||
<string name="revanced_spoof_video_streams_about_title">āϏā§āĻĒā§āĻĢāĻŋāĻ āĻāϰ āĻĒāĻžāϰā§āĻļā§āĻŦāĻĒā§āϰāϤāĻŋāĻā§āϰāĻŋāϝāĻŧāĻž</string>
|
||||
<string name="revanced_spoof_video_streams_about_summary">"âĸ āĻ
āĻĄāĻŋāĻ āĻā§āϰā§āϝāĻžāĻ āĻŽā§āύ⧠āĻ
āύā§āĻĒāϏā§āĻĨāĻŋāϤ
|
||||
âĸ āϏā§āĻĨāĻŋāϤāĻŋāĻļā§āϞ āĻāϞāĻŋāĻāĻŽ āĻāĻĒāϞāĻŦā§āϧ āύāϝāĻŧ
|
||||
âĸ āĻā§āϰ āĻāϰ⧠āĻŽā§āϞ āĻ
āĻĄāĻŋāĻ āĻāĻĒāϞāĻŦā§āϧ āύāϝāĻŧ⧎"</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">āĻĄāĻŋāĻĢāϞā§āĻ āĻ
āĻĄāĻŋāĻ āϏā§āĻā§āϰāĻŋāĻŽ āĻāĻžāώāĻž</string>
|
||||
<string name="revanced_spoof_video_streams_language_DEFAULT">āĻ
ā§āϝāĻžāĻĒ āĻāĻžāώāĻž</string>
|
||||
<string name="revanced_spoof_video_streams_language_AR">āĻāϰāĻŦāĻŋ</string>
|
||||
@@ -1332,8 +1330,6 @@ AVC-āĻāϰ āϏāϰā§āĻŦā§āĻā§āĻ āϰā§āĻā§āϞāĻŋāĻāĻļāύ 1080p, Opus āĻ
|
||||
<string name="revanced_spoof_video_streams_language_OR">āĻāĻĄāĻŧāĻŋāϝāĻŧāĻž</string>
|
||||
<string name="revanced_spoof_video_streams_language_PA">āĻĒāĻā§āĻāĻžāĻŦāĻŋ</string>
|
||||
<string name="revanced_spoof_video_streams_language_PL">āĻĒā§āϞāĻŋāĻļ</string>
|
||||
<string name="revanced_spoof_video_streams_language_PT_BR">āĻĒāϰā§āϤā§āĻāĻŋāĻ (āĻŦā§āϰāĻžāĻāĻŋāϞ)</string>
|
||||
<string name="revanced_spoof_video_streams_language_PT_PT">āĻĒāϰā§āϤā§āĻāĻŋāĻ (āĻĒāϰā§āϤā§āĻāĻžāϞ)</string>
|
||||
<string name="revanced_spoof_video_streams_language_RO">āϰā§āĻŽāĻžāύā§āϝāĻŧ</string>
|
||||
<string name="revanced_spoof_video_streams_language_RU">āϰāĻžāĻļāĻŋāϝāĻŧāĻžāύ</string>
|
||||
<string name="revanced_spoof_video_streams_language_SK">āϏā§āϞā§āĻāĻžāĻ</string>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user