Compare commits

...

32 Commits

Author SHA1 Message Date
semantic-release-bot
bdbe96beba chore: Release v5.34.0-dev.7 [skip ci]
# [5.34.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.6...v5.34.0-dev.7) (2025-08-13)

### Bug Fixes

* **YouTube - Video quality:** Fix additional incorrect quality resolutions used by YouTube ([6bd9e49](6bd9e49c7a))
2025-08-13 19:20:51 +00:00
LisoUseInAIKyrios
6bd9e49c7a fix(YouTube - Video quality): Fix additional incorrect quality resolutions used by YouTube 2025-08-13 15:16:45 -04:00
semantic-release-bot
f904ca6d7e chore: Release v5.34.0-dev.6 [skip ci]
# [5.34.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.5...v5.34.0-dev.6) (2025-08-11)

### Bug Fixes

* **YouTube - Video quality:** Show FHD+ icon for 1080p 60fps enhanced bitrate ([e579c56](e579c56921))
2025-08-11 01:21:07 +00:00
LisoUseInAIKyrios
e579c56921 fix(YouTube - Video quality): Show FHD+ icon for 1080p 60fps enhanced bitrate 2025-08-10 21:17:32 -04:00
github-actions[bot]
83f239065a chore: Sync translations (#5637) 2025-08-10 21:13:31 -04:00
semantic-release-bot
6499318f33 chore: Release v5.34.0-dev.5 [skip ci]
# [5.34.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.4...v5.34.0-dev.5) (2025-08-10)

### Features

* **YouTube - Hide player flyout menu items:** Add option to hide quality flyout menu ([809e013](809e013c4e))
2025-08-10 13:57:25 +00:00
LisoUseInAIKyrios
809e013c4e feat(YouTube - Hide player flyout menu items): Add option to hide quality flyout menu 2025-08-10 09:54:40 -04:00
semantic-release-bot
182829d51c chore: Release v5.34.0-dev.4 [skip ci]
# [5.34.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.3...v5.34.0-dev.4) (2025-08-10)

### Bug Fixes

* **YouTube - Hide layout components:** Do not hide community posts on channel profiles ([#5634](https://github.com/ReVanced/revanced-patches/issues/5634)) ([61824ad](61824ade23))
2025-08-10 13:11:44 +00:00
LisoUseInAIKyrios
61824ade23 fix(YouTube - Hide layout components): Do not hide community posts on channel profiles (#5634) 2025-08-10 09:09:08 -04:00
LisoUseInAIKyrios
ff4308e961 refactor(YouTube Music - Hide category bar): Fix possible crash when patching certain app targets 2025-08-09 11:13:35 -04:00
semantic-release-bot
b5eb13c0a8 chore: Release v5.34.0-dev.3 [skip ci]
# [5.34.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.2...v5.34.0-dev.3) (2025-08-09)

### Bug Fixes

* **pixiv - Hide ads:** Constrain patch to last working app target ([b702dce](b702dceda0))
2025-08-09 15:06:42 +00:00
LisoUseInAIKyrios
b702dceda0 fix(pixiv - Hide ads): Constrain patch to last working app target 2025-08-09 11:04:07 -04:00
semantic-release-bot
d616652058 chore: Release v5.34.0-dev.2 [skip ci]
# [5.34.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.1...v5.34.0-dev.2) (2025-08-09)

### Bug Fixes

* **Backdrops:** Remove broken patch that is no longer supported ([#5627](https://github.com/ReVanced/revanced-patches/issues/5627)) ([c3e571e](c3e571e765))

### Features

* **YouTube - Playback speed:** Show current playback speed on player speed dialog button ([#5607](https://github.com/ReVanced/revanced-patches/issues/5607)) ([30176a3](30176a3318))
2025-08-09 01:31:11 +00:00
LisoUseInAIKyrios
c3e571e765 fix(Backdrops): Remove broken patch that is no longer supported (#5627) 2025-08-08 21:28:07 -04:00
MarcaD
30176a3318 feat(YouTube - Playback speed): Show current playback speed on player speed dialog button (#5607)
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
2025-08-08 21:27:52 -04:00
semantic-release-bot
9c0638d128 chore: Release v5.34.0-dev.1 [skip ci]
# [5.34.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.33.0...v5.34.0-dev.1) (2025-08-08)

### Bug Fixes

* **Twitch:** Constrain patches to last working app targets ([#5373](https://github.com/ReVanced/revanced-patches/issues/5373)) ([d7eb6e8](d7eb6e87a5))

### Features

* **Instagram:** Support latest app version ([#5611](https://github.com/ReVanced/revanced-patches/issues/5611)) ([562e005](562e005772))
2025-08-08 01:55:22 +00:00
LisoUseInAIKyrios
d7eb6e87a5 fix(Twitch): Constrain patches to last working app targets (#5373) 2025-08-07 21:51:52 -04:00
LisoUseInAIKyrios
562e005772 feat(Instagram): Support latest app version (#5611) 2025-08-07 21:51:01 -04:00
github-actions[bot]
f61218de52 chore: Sync translations (#5616) 2025-08-07 21:50:45 -04:00
semantic-release-bot
a19b670e19 chore: Release v5.33.0 [skip ci]
# [5.33.0](https://github.com/ReVanced/revanced-patches/compare/v5.32.0...v5.33.0) (2025-08-05)

### Bug Fixes

* **Messenger - Hide Facebook button:** Support the latest app version ([#5590](https://github.com/ReVanced/revanced-patches/issues/5590)) ([a28891e](a28891e5f3))
* **NFC Tools:** Remove broken patch that is no longer supported ([#5584](https://github.com/ReVanced/revanced-patches/issues/5584)) ([2e177a8](2e177a8839))
* **YouTube - Force original audio:** Disable a/b feature flag that forces localized audio ([#5582](https://github.com/ReVanced/revanced-patches/issues/5582)) ([1dd01cf](1dd01cf54a))
* **YouTube - Litho filter:** Correctly filter identifier of older YouTube targets ([b1d164b](b1d164b446))
* **YouTube - Playback speed:** Use old speed menu for player button if enabled ([a4817df](a4817dfdd0))
* **YouTube - Video quality:** Fix 144p default not always used ([9afa7d2](9afa7d2ac6))
* **YouTube - Video quality:** Fix dialog quality list check mark not always shown ([1bc63e5](1bc63e50a7))
* **YouTube - Video quality:** Fix wrong qualities sometimes shown in player button dialog ([178eed7](178eed7fcd))
* **YouTube - Video quality:** Use 1080p enhanced bitrate for Premium users ([#5565](https://github.com/ReVanced/revanced-patches/issues/5565)) ([1adbd56](1adbd563b2))

### Features

* **ORF ON:** Add `Remove root detection` patch ([#5551](https://github.com/ReVanced/revanced-patches/issues/5551)) ([d92362b](d92362b0d9))
* **YouTube - Playback speed:** Add "Restore old playback speed menu" option ([#5552](https://github.com/ReVanced/revanced-patches/issues/5552)) ([e9e4cf3](e9e4cf39b6))
* **YouTube:** Add player button to change video quality ([#5435](https://github.com/ReVanced/revanced-patches/issues/5435)) ([7bdc328](7bdc32867a))

### Performance Improvements

* **YouTube:** Filter identifier callback only on root component creation ([#5558](https://github.com/ReVanced/revanced-patches/issues/5558)) ([5d08fdd](5d08fdddb8))
2025-08-05 17:57:09 +00:00
LisoUseInAIKyrios
300d816350 chore: Merge branch dev to main (#5553) 2025-08-05 13:53:31 -04:00
github-actions[bot]
63d64a5c87 chore: Sync translations (#5595) 2025-08-05 13:52:06 -04:00
semantic-release-bot
0cfc31c8f7 chore: Release v5.33.0-dev.13 [skip ci]
# [5.33.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.12...v5.33.0-dev.13) (2025-08-05)

### Bug Fixes

* **Messenger - Hide Facebook button:** Support the latest app version ([#5590](https://github.com/ReVanced/revanced-patches/issues/5590)) ([a28891e](a28891e5f3))
2025-08-05 03:23:38 +00:00
Dawid Krajcarz
a28891e5f3 fix(Messenger - Hide Facebook button): Support the latest app version (#5590) 2025-08-04 23:21:10 -04:00
semantic-release-bot
36036b082d chore: Release v5.33.0-dev.12 [skip ci]
# [5.33.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.11...v5.33.0-dev.12) (2025-08-04)

### Bug Fixes

* **YouTube - Video quality:** Fix dialog quality list check mark not always shown ([1bc63e5](1bc63e50a7))
2025-08-04 19:19:31 +00:00
LisoUseInAIKyrios
1bc63e50a7 fix(YouTube - Video quality): Fix dialog quality list check mark not always shown 2025-08-04 15:17:00 -04:00
semantic-release-bot
4b2b5e3029 chore: Release v5.33.0-dev.11 [skip ci]
# [5.33.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.10...v5.33.0-dev.11) (2025-08-04)

### Bug Fixes

* **YouTube - Video quality:** Fix 144p default not always used ([9afa7d2](9afa7d2ac6))
2025-08-04 19:03:03 +00:00
LisoUseInAIKyrios
9afa7d2ac6 fix(YouTube - Video quality): Fix 144p default not always used 2025-08-04 15:00:14 -04:00
semantic-release-bot
1a8146dbc8 chore: Release v5.33.0-dev.10 [skip ci]
# [5.33.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.9...v5.33.0-dev.10) (2025-08-04)

### Bug Fixes

* **YouTube - Video quality:** Fix wrong qualities sometimes shown in player button dialog ([178eed7](178eed7fcd))
2025-08-04 17:23:50 +00:00
LisoUseInAIKyrios
178eed7fcd fix(YouTube - Video quality): Fix wrong qualities sometimes shown in player button dialog 2025-08-04 13:21:02 -04:00
semantic-release-bot
621292644c chore: Release v5.33.0-dev.9 [skip ci]
# [5.33.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.8...v5.33.0-dev.9) (2025-08-04)

### Bug Fixes

* **YouTube - Force original audio:** Disable a/b feature flag that forces localized audio ([#5582](https://github.com/ReVanced/revanced-patches/issues/5582)) ([1dd01cf](1dd01cf54a))
2025-08-04 01:27:12 +00:00
LisoUseInAIKyrios
1dd01cf54a fix(YouTube - Force original audio): Disable a/b feature flag that forces localized audio (#5582) 2025-08-03 21:23:27 -04:00
138 changed files with 1354 additions and 999 deletions

View File

@@ -1,3 +1,124 @@
# [5.34.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.6...v5.34.0-dev.7) (2025-08-13)
### Bug Fixes
* **YouTube - Video quality:** Fix additional incorrect quality resolutions used by YouTube ([a2a1fbe](https://github.com/ReVanced/revanced-patches/commit/a2a1fbe2959be8334c54cfc3426c24a960c55c8f))
# [5.34.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.5...v5.34.0-dev.6) (2025-08-11)
### Bug Fixes
* **YouTube - Video quality:** Show FHD+ icon for 1080p 60fps enhanced bitrate ([76bed37](https://github.com/ReVanced/revanced-patches/commit/76bed3734093713af24ef065d5ffc5b1cd83f29a))
# [5.34.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.4...v5.34.0-dev.5) (2025-08-10)
### Features
* **YouTube - Hide player flyout menu items:** Add option to hide quality flyout menu ([eb55068](https://github.com/ReVanced/revanced-patches/commit/eb5506856a2eaf2a8585e598868ddba3e1429159))
# [5.34.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.3...v5.34.0-dev.4) (2025-08-10)
### Bug Fixes
* **YouTube - Hide layout components:** Do not hide community posts on channel profiles ([#5634](https://github.com/ReVanced/revanced-patches/issues/5634)) ([9e3d5a2](https://github.com/ReVanced/revanced-patches/commit/9e3d5a2b36106479470f3f69920518b57e8c4dca))
# [5.34.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.2...v5.34.0-dev.3) (2025-08-09)
### Bug Fixes
* **pixiv - Hide ads:** Constrain patch to last working app target ([d8ea56c](https://github.com/ReVanced/revanced-patches/commit/d8ea56ca4be47df1c43f96ec41b91c800f1d9daf))
# [5.34.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.34.0-dev.1...v5.34.0-dev.2) (2025-08-09)
### Bug Fixes
* **Backdrops:** Remove broken patch that is no longer supported ([#5627](https://github.com/ReVanced/revanced-patches/issues/5627)) ([ebb8332](https://github.com/ReVanced/revanced-patches/commit/ebb83320838aa99dd4417d45a50333dd42c1218a))
### Features
* **YouTube - Playback speed:** Show current playback speed on player speed dialog button ([#5607](https://github.com/ReVanced/revanced-patches/issues/5607)) ([279436a](https://github.com/ReVanced/revanced-patches/commit/279436a3657b50f98bb4cc64dc88dc14e422f204))
# [5.34.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.33.0...v5.34.0-dev.1) (2025-08-08)
### Bug Fixes
* **Twitch:** Constrain patches to last working app targets ([#5373](https://github.com/ReVanced/revanced-patches/issues/5373)) ([29a4748](https://github.com/ReVanced/revanced-patches/commit/29a47481c4efa209a3a53df60613b59a73adbe07))
### Features
* **Instagram:** Support latest app version ([#5611](https://github.com/ReVanced/revanced-patches/issues/5611)) ([26fe690](https://github.com/ReVanced/revanced-patches/commit/26fe690dfbefe6c412c5f81f208a3b1d2fbd7a0a))
# [5.33.0](https://github.com/ReVanced/revanced-patches/compare/v5.32.0...v5.33.0) (2025-08-05)
### Bug Fixes
* **Messenger - Hide Facebook button:** Support the latest app version ([#5590](https://github.com/ReVanced/revanced-patches/issues/5590)) ([0cab98d](https://github.com/ReVanced/revanced-patches/commit/0cab98df1689dbf7a042f18f4a961d47da1430ad))
* **NFC Tools:** Remove broken patch that is no longer supported ([#5584](https://github.com/ReVanced/revanced-patches/issues/5584)) ([cd3a6be](https://github.com/ReVanced/revanced-patches/commit/cd3a6be75c6bd3cc33c0b17a044bd6147f27b5ce))
* **YouTube - Force original audio:** Disable a/b feature flag that forces localized audio ([#5582](https://github.com/ReVanced/revanced-patches/issues/5582)) ([9fe13ee](https://github.com/ReVanced/revanced-patches/commit/9fe13ee1af104c009efd19b826adef375e48e191))
* **YouTube - Litho filter:** Correctly filter identifier of older YouTube targets ([bf29d69](https://github.com/ReVanced/revanced-patches/commit/bf29d6909e389819bad878ad3b94bbc90d823cc9))
* **YouTube - Playback speed:** Use old speed menu for player button if enabled ([1e8f436](https://github.com/ReVanced/revanced-patches/commit/1e8f4368e117f4b278c24709231cb32546e46dc0))
* **YouTube - Video quality:** Fix 144p default not always used ([2f7483a](https://github.com/ReVanced/revanced-patches/commit/2f7483a2d789c28a243b58bb7a252c0d590858ee))
* **YouTube - Video quality:** Fix dialog quality list check mark not always shown ([295f0f2](https://github.com/ReVanced/revanced-patches/commit/295f0f216b5e8aa9d68457862e73e312b7342703))
* **YouTube - Video quality:** Fix wrong qualities sometimes shown in player button dialog ([7378ae3](https://github.com/ReVanced/revanced-patches/commit/7378ae3c5fc88f91bf5cd6db47c6cd170a8c5a4f))
* **YouTube - Video quality:** Use 1080p enhanced bitrate for Premium users ([#5565](https://github.com/ReVanced/revanced-patches/issues/5565)) ([bd3ace0](https://github.com/ReVanced/revanced-patches/commit/bd3ace0bd04ccd0369adb49d63aa0cf986402346))
### Features
* **ORF ON:** Add `Remove root detection` patch ([#5551](https://github.com/ReVanced/revanced-patches/issues/5551)) ([6c6aa35](https://github.com/ReVanced/revanced-patches/commit/6c6aa35411a139dddc3a15dd757fbeded5d1a0a3))
* **YouTube - Playback speed:** Add "Restore old playback speed menu" option ([#5552](https://github.com/ReVanced/revanced-patches/issues/5552)) ([b01f15b](https://github.com/ReVanced/revanced-patches/commit/b01f15b9acb0427aed99b0141ae271831b7936bf))
* **YouTube:** Add player button to change video quality ([#5435](https://github.com/ReVanced/revanced-patches/issues/5435)) ([d5f51bf](https://github.com/ReVanced/revanced-patches/commit/d5f51bf400dd22626ff65d7563b6fde70d53fb25))
### Performance Improvements
* **YouTube:** Filter identifier callback only on root component creation ([#5558](https://github.com/ReVanced/revanced-patches/issues/5558)) ([ccac46e](https://github.com/ReVanced/revanced-patches/commit/ccac46eebc2e14b094454e37ef4461d48a62c53f))
# [5.33.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.12...v5.33.0-dev.13) (2025-08-05)
### Bug Fixes
* **Messenger - Hide Facebook button:** Support the latest app version ([#5590](https://github.com/ReVanced/revanced-patches/issues/5590)) ([0cab98d](https://github.com/ReVanced/revanced-patches/commit/0cab98df1689dbf7a042f18f4a961d47da1430ad))
# [5.33.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.11...v5.33.0-dev.12) (2025-08-04)
### Bug Fixes
* **YouTube - Video quality:** Fix dialog quality list check mark not always shown ([295f0f2](https://github.com/ReVanced/revanced-patches/commit/295f0f216b5e8aa9d68457862e73e312b7342703))
# [5.33.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.10...v5.33.0-dev.11) (2025-08-04)
### Bug Fixes
* **YouTube - Video quality:** Fix 144p default not always used ([2f7483a](https://github.com/ReVanced/revanced-patches/commit/2f7483a2d789c28a243b58bb7a252c0d590858ee))
# [5.33.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.9...v5.33.0-dev.10) (2025-08-04)
### Bug Fixes
* **YouTube - Video quality:** Fix wrong qualities sometimes shown in player button dialog ([7378ae3](https://github.com/ReVanced/revanced-patches/commit/7378ae3c5fc88f91bf5cd6db47c6cd170a8c5a4f))
# [5.33.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.8...v5.33.0-dev.9) (2025-08-04)
### Bug Fixes
* **YouTube - Force original audio:** Disable a/b feature flag that forces localized audio ([#5582](https://github.com/ReVanced/revanced-patches/issues/5582)) ([9fe13ee](https://github.com/ReVanced/revanced-patches/commit/9fe13ee1af104c009efd19b826adef375e48e191))
# [5.33.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.7...v5.33.0-dev.8) (2025-08-03) # [5.33.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.7...v5.33.0-dev.8) (2025-08-03)

View File

@@ -329,7 +329,7 @@ public class Utils {
return (R) child; return (R) child;
} }
throw new IllegalArgumentException("View with resource name '" + str + "' not found"); throw new IllegalArgumentException("View with resource name not found: " + str);
} }
/** /**

View File

@@ -1,16 +1,20 @@
package app.revanced.extension.youtube package app.revanced.extension.youtube
import app.revanced.extension.shared.Logger
import java.util.Collections
/** /**
* generic event provider class * generic event provider class
*/ */
class Event<T> { class Event<T> {
private val eventListeners = mutableSetOf<(T) -> Unit>() private val eventListeners = Collections.synchronizedSet(mutableSetOf<(T) -> Unit>())
operator fun plusAssign(observer: (T) -> Unit) { operator fun plusAssign(observer: (T) -> Unit) {
addObserver(observer) addObserver(observer)
} }
fun addObserver(observer: (T) -> Unit) { fun addObserver(observer: (T) -> Unit) {
Logger.printDebug { "Adding observer: $observer" }
eventListeners.add(observer) eventListeners.add(observer)
} }
@@ -23,7 +27,8 @@ class Event<T> {
} }
operator fun invoke(value: T) { operator fun invoke(value: T) {
for (observer in eventListeners) for (observer in eventListeners) {
observer.invoke(value) observer.invoke(value)
}
} }
} }

View File

@@ -24,6 +24,16 @@ public class ForceOriginalAudioPatch {
} }
} }
/**
* Injection point.
*/
public static boolean ignoreDefaultAudioStream(boolean original) {
if (Settings.FORCE_ORIGINAL_AUDIO.get()) {
return false;
}
return original;
}
/** /**
* Injection point. * Injection point.
*/ */
@@ -50,7 +60,6 @@ public class ForceOriginalAudioPatch {
return isOriginal; return isOriginal;
} catch (Exception ex) { } catch (Exception ex) {
Logger.printException(() -> "isDefaultAudioStream failure", ex); Logger.printException(() -> "isDefaultAudioStream failure", ex);
return isDefault; return isDefault;
} }
} }

View File

@@ -1,12 +1,18 @@
package app.revanced.extension.youtube.patches; package app.revanced.extension.youtube.patches;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.libraries.youtube.innertube.model.media.VideoQuality;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.Objects; import java.util.Objects;
import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils; import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.Event;
import app.revanced.extension.youtube.shared.ShortsPlayerState;
import app.revanced.extension.youtube.shared.VideoState; import app.revanced.extension.youtube.shared.VideoState;
/** /**
@@ -16,11 +22,30 @@ import app.revanced.extension.youtube.shared.VideoState;
public final class VideoInformation { public final class VideoInformation {
public interface PlaybackController { public interface PlaybackController {
// Methods are added to YT classes during patching. // Methods are added during patching.
boolean seekTo(long videoTime); boolean patch_seekTo(long videoTime);
void seekToRelative(long videoTimeOffset); void patch_seekToRelative(long videoTimeOffset);
} }
/**
* Interface to use obfuscated methods.
*/
public interface VideoQualityMenuInterface {
// Method is added during patching.
void patch_setQuality(VideoQuality quality);
}
/**
* Video resolution of the automatic quality option..
*/
public static final int AUTOMATIC_VIDEO_QUALITY_VALUE = -2;
/**
* Video quality names are the same text for all languages.
* Premium can be "1080p Premium" or "1080p60 Premium"
*/
public static final String VIDEO_QUALITY_PREMIUM_NAME = "Premium";
private static final float DEFAULT_YOUTUBE_PLAYBACK_SPEED = 1.0f; private static final float DEFAULT_YOUTUBE_PLAYBACK_SPEED = 1.0f;
/** /**
* Prefix present in all Short player parameters signature. * Prefix present in all Short player parameters signature.
@@ -30,12 +55,10 @@ public final class VideoInformation {
private static WeakReference<PlaybackController> playerControllerRef = new WeakReference<>(null); private static WeakReference<PlaybackController> playerControllerRef = new WeakReference<>(null);
private static WeakReference<PlaybackController> mdxPlayerDirectorRef = new WeakReference<>(null); private static WeakReference<PlaybackController> mdxPlayerDirectorRef = new WeakReference<>(null);
@NonNull
private static String videoId = ""; private static String videoId = "";
private static long videoLength = 0; private static long videoLength = 0;
private static long videoTime = -1; private static long videoTime = -1;
@NonNull
private static volatile String playerResponseVideoId = ""; private static volatile String playerResponseVideoId = "";
private static volatile boolean playerResponseVideoIdIsShort; private static volatile boolean playerResponseVideoIdIsShort;
private static volatile boolean videoIdIsShort; private static volatile boolean videoIdIsShort;
@@ -45,6 +68,44 @@ public final class VideoInformation {
*/ */
private static float playbackSpeed = DEFAULT_YOUTUBE_PLAYBACK_SPEED; private static float playbackSpeed = DEFAULT_YOUTUBE_PLAYBACK_SPEED;
private static int desiredVideoResolution = AUTOMATIC_VIDEO_QUALITY_VALUE;
private static boolean qualityNeedsUpdating;
/**
* The available qualities of the current video.
*/
@Nullable
private static VideoQuality[] currentQualities;
/**
* The current quality of the video playing.
* This is always the actual quality even if Automatic quality is active.
*/
@Nullable
private static VideoQuality currentQuality;
/**
* The current VideoQualityMenuInterface, set during setVideoQuality.
*/
@Nullable
private static VideoQualityMenuInterface currentMenuInterface;
/**
* Callback for when the current quality changes.
*/
public static final Event<VideoQuality> onQualityChange = new Event<>();
@Nullable
public static VideoQuality[] getCurrentQualities() {
return currentQualities;
}
@Nullable
public static VideoQuality getCurrentQuality() {
return currentQuality;
}
/** /**
* Injection point. * Injection point.
* *
@@ -52,12 +113,18 @@ public final class VideoInformation {
*/ */
public static void initialize(@NonNull PlaybackController playerController) { public static void initialize(@NonNull PlaybackController playerController) {
try { try {
Logger.printDebug(() -> "newVideoStarted");
playerControllerRef = new WeakReference<>(Objects.requireNonNull(playerController)); playerControllerRef = new WeakReference<>(Objects.requireNonNull(playerController));
videoTime = -1; videoTime = -1;
videoLength = 0; videoLength = 0;
playbackSpeed = DEFAULT_YOUTUBE_PLAYBACK_SPEED; playbackSpeed = DEFAULT_YOUTUBE_PLAYBACK_SPEED;
desiredVideoResolution = AUTOMATIC_VIDEO_QUALITY_VALUE;
currentQualities = null;
currentMenuInterface = null;
setCurrentQuality(null);
} catch (Exception ex) { } catch (Exception ex) {
Logger.printException(() -> "Failed to initialize", ex); Logger.printException(() -> "initialize failure", ex);
} }
} }
@@ -197,14 +264,14 @@ public final class VideoInformation {
if (controller == null) { if (controller == null) {
Logger.printDebug(() -> "Cannot seekTo because player controller is null"); Logger.printDebug(() -> "Cannot seekTo because player controller is null");
} else { } else {
if (controller.seekTo(adjustedSeekTime)) return true; if (controller.patch_seekTo(adjustedSeekTime)) return true;
Logger.printDebug(() -> "seekTo did not succeeded. Trying MXD."); Logger.printDebug(() -> "seekTo did not succeeded. Trying MXD.");
// Else the video is loading or changing videos, or video is casting to a different device. // Else the video is loading or changing videos, or video is casting to a different device.
} }
// Try calling the seekTo method of the MDX player director (called when casting). // Try calling the seekTo method of the MDX player director (called when casting).
// The difference has to be a different second mark in order to avoid infinite skip loops // The difference has to be a different second mark in order to avoid infinite skip loops
// as the Lounge API only supports seconds. // as the Lounge API only supports whole seconds.
if (adjustedSeekTime / 1000 == videoTime / 1000) { if (adjustedSeekTime / 1000 == videoTime / 1000) {
Logger.printDebug(() -> "Skipping seekTo for MDX because seek time is too small " Logger.printDebug(() -> "Skipping seekTo for MDX because seek time is too small "
+ "(" + (adjustedSeekTime - videoTime) + "ms)"); + "(" + (adjustedSeekTime - videoTime) + "ms)");
@@ -217,9 +284,9 @@ public final class VideoInformation {
return false; return false;
} }
return controller.seekTo(adjustedSeekTime); return controller.patch_seekTo(adjustedSeekTime);
} catch (Exception ex) { } catch (Exception ex) {
Logger.printException(() -> "Failed to seek", ex); Logger.printException(() -> "seekTo failure", ex);
return false; return false;
} }
} }
@@ -239,7 +306,7 @@ public final class VideoInformation {
if (controller == null) { if (controller == null) {
Logger.printDebug(() -> "Cannot seek relative as player controller is null"); Logger.printDebug(() -> "Cannot seek relative as player controller is null");
} else { } else {
controller.seekToRelative(seekTime); controller.patch_seekToRelative(seekTime);
} }
// Adjust the fine adjustment function so it's at least 1 second before/after. // Adjust the fine adjustment function so it's at least 1 second before/after.
@@ -255,10 +322,10 @@ public final class VideoInformation {
if (controller == null) { if (controller == null) {
Logger.printDebug(() -> "Cannot seek relative as MXD player controller is null"); Logger.printDebug(() -> "Cannot seek relative as MXD player controller is null");
} else { } else {
controller.seekToRelative(adjustedSeekTime); controller.patch_seekToRelative(adjustedSeekTime);
} }
} catch (Exception ex) { } catch (Exception ex) {
Logger.printException(() -> "Failed to seek relative", ex); Logger.printException(() -> "seekToRelative failure", ex);
} }
} }
@@ -339,14 +406,13 @@ public final class VideoInformation {
} }
/** /**
* @return If the playback is at the end of the video.
* <p>
* If video is playing in the background with no video visible, * If video is playing in the background with no video visible,
* this always returns false (even if the video is actually at the end). * this always returns false (even if the video is actually at the end).
* <p> * <p>
* This is equivalent to checking for {@link VideoState#ENDED}, * This is equivalent to checking for {@link VideoState#ENDED},
* but can give a more up-to-date result for code calling from some hooks. * but can give a more up-to-date result for code calling from some hooks.
* *
* @return If the playback is at the end of the video.
* @see VideoState * @see VideoState
*/ */
@SuppressWarnings("BooleanMethodIsAlwaysInverted") @SuppressWarnings("BooleanMethodIsAlwaysInverted")
@@ -373,4 +439,134 @@ public final class VideoInformation {
playbackSpeed = newlyLoadedPlaybackSpeed; playbackSpeed = newlyLoadedPlaybackSpeed;
} }
} }
/**
* @param resolution The desired video quality resolution to use.
*/
public static void setDesiredVideoResolution(int resolution) {
Utils.verifyOnMainThread();
Logger.printDebug(() -> "Setting desired video resolution: " + resolution);
desiredVideoResolution = resolution;
qualityNeedsUpdating = true;
}
private static void setCurrentQuality(@Nullable VideoQuality quality) {
Utils.verifyOnMainThread();
if (currentQuality != quality) {
Logger.printDebug(() -> "Current quality changed to: " + quality);
currentQuality = quality;
onQualityChange.invoke(quality);
}
}
/**
* Forcefully changes the video quality of the currently playing video.
*/
public static void changeQuality(VideoQuality quality) {
Utils.verifyOnMainThread();
if (currentMenuInterface == null) {
Logger.printException(() -> "Cannot change quality, menu interface is null");
return;
}
currentMenuInterface.patch_setQuality(quality);
}
/**
* Injection point. Fixes bad data used by YouTube.
* Issue can be reproduced by selecting 480p quality on any Short,
* and occasionally with random regular videos.
*/
public static int fixVideoQualityResolution(String name, int quality) {
try {
if (!name.startsWith(Integer.toString(quality))) {
final int suffixIndex = name.indexOf('p');
if (suffixIndex > 0) {
final int fixedQuality = Integer.parseInt(name.substring(0, suffixIndex));
Logger.printDebug(() -> "Fixing wrong quality resolution from: " +
name + "(" + quality + ") to: " + name + ")" + fixedQuality + ")");
return fixedQuality;
}
}
} catch (Exception ex) {
Logger.printException(() -> "fixVideoQualityResolution failed", ex);
}
return quality;
}
/**
* Injection point.
*
* @param qualities Video qualities available, ordered from largest to smallest, with index 0 being the 'automatic' value of -2
* @param originalQualityIndex quality index to use, as chosen by YouTube
*/
public static int setVideoQuality(VideoQuality[] qualities, VideoQualityMenuInterface menu, int originalQualityIndex) {
try {
Utils.verifyOnMainThread();
currentMenuInterface = menu;
final boolean availableQualitiesChanged = (currentQualities == null)
|| !Arrays.equals(currentQualities, qualities);
if (availableQualitiesChanged) {
currentQualities = qualities;
Logger.printDebug(() -> "VideoQualities: " + Arrays.toString(currentQualities));
}
VideoQuality updatedCurrentQuality = qualities[originalQualityIndex];
if (updatedCurrentQuality.patch_getResolution() != AUTOMATIC_VIDEO_QUALITY_VALUE
&& (currentQuality == null || currentQuality != updatedCurrentQuality)) {
setCurrentQuality(updatedCurrentQuality);
}
final int preferredQuality = desiredVideoResolution;
if (preferredQuality == AUTOMATIC_VIDEO_QUALITY_VALUE) {
return originalQualityIndex; // Nothing to do.
}
// After changing videos the qualities can initially be for the prior video.
// If the qualities have changed and the default is not auto then an update is needed.
if (qualityNeedsUpdating) {
qualityNeedsUpdating = false;
} else if (!availableQualitiesChanged) {
return originalQualityIndex;
}
// Find the highest quality that is equal to or less than the preferred.
int i = 0;
final int lastQualityIndex = qualities.length - 1;
for (VideoQuality quality : qualities) {
final int qualityResolution = quality.patch_getResolution();
if ((qualityResolution != AUTOMATIC_VIDEO_QUALITY_VALUE && qualityResolution <= preferredQuality)
// Use the lowest video quality if the default is lower than all available.
|| i == lastQualityIndex) {
final boolean qualityNeedsChange = (i != originalQualityIndex);
Logger.printDebug(() -> qualityNeedsChange
? "Changing video quality from: " + updatedCurrentQuality + " to: " + quality
: "Video is already the preferred quality: " + quality
);
// On first load of a new regular video, if the video is already the
// desired quality then the quality flyout will show 'Auto' (ie: Auto (720p)).
//
// To prevent user confusion, set the video index even if the
// quality is already correct so the UI picker will not display "Auto".
//
// Only change Shorts quality if the quality actually needs to change,
// because the "auto" option is not shown in the flyout
// and setting the same quality again can cause the Short to restart.
if (qualityNeedsChange || !ShortsPlayerState.isOpen()) {
changeQuality(quality);
return i;
}
return originalQualityIndex;
}
i++;
}
} catch (Exception ex) {
Logger.printException(() -> "setVideoQuality failure", ex);
}
return originalQualityIndex;
}
} }

View File

@@ -40,7 +40,6 @@ abstract class Filter {
/** /**
* Adds callbacks to {@link #isFiltered(String, String, byte[], StringFilterGroup, FilterContentType, int)} * Adds callbacks to {@link #isFiltered(String, String, byte[], StringFilterGroup, FilterContentType, int)}
* if any of the groups are found. * if any of the groups are found.
* <p>
*/ */
protected final void addIdentifierCallbacks(StringFilterGroup... groups) { protected final void addIdentifierCallbacks(StringFilterGroup... groups) {
identifierCallbacks.addAll(Arrays.asList(groups)); identifierCallbacks.addAll(Arrays.asList(groups));
@@ -58,7 +57,6 @@ abstract class Filter {
* Called after an enabled filter has been matched. * Called after an enabled filter has been matched.
* Default implementation is to always filter the matched component and log the action. * Default implementation is to always filter the matched component and log the action.
* Subclasses can perform additional or different checks if needed. * Subclasses can perform additional or different checks if needed.
*
* <p> * <p>
* Method is called off the main thread. * Method is called off the main thread.
* *

View File

@@ -32,6 +32,7 @@ public final class LayoutComponentsFilter extends Filter {
); );
private final StringTrieSearch exceptions = new StringTrieSearch(); private final StringTrieSearch exceptions = new StringTrieSearch();
private final StringFilterGroup communityPosts;
private final StringFilterGroup surveys; private final StringFilterGroup surveys;
private final StringFilterGroup notifyMe; private final StringFilterGroup notifyMe;
private final StringFilterGroup singleItemInformationPanel; private final StringFilterGroup singleItemInformationPanel;
@@ -68,7 +69,7 @@ public final class LayoutComponentsFilter extends Filter {
// Paths. // Paths.
final var communityPosts = new StringFilterGroup( communityPosts = new StringFilterGroup(
Settings.HIDE_COMMUNITY_POSTS, Settings.HIDE_COMMUNITY_POSTS,
"post_base_wrapper", // may be obsolete and no longer needed. "post_base_wrapper", // may be obsolete and no longer needed.
"text_post_root.eml", "text_post_root.eml",
@@ -325,6 +326,12 @@ public final class LayoutComponentsFilter extends Filter {
return channelProfileBuffer.check(buffer).isFiltered(); return channelProfileBuffer.check(buffer).isFiltered();
} }
if (matchedGroup == communityPosts && NavigationBar.isBackButtonVisible()) {
// Allow community posts on channel profile page,
// or if viewing an individual channel in the feed.
return false;
}
if (exceptions.matches(path)) return false; // Exceptions are not filtered. if (exceptions.matches(path)) return false; // Exceptions are not filtered.
if (matchedGroup == compactChannelBarInner) { if (matchedGroup == compactChannelBarInner) {

View File

@@ -3,7 +3,7 @@ package app.revanced.extension.youtube.patches.components;
import app.revanced.extension.shared.settings.Setting; import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch; import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.PlayerType; import app.revanced.extension.youtube.shared.ShortsPlayerState;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class PlayerFlyoutMenuItemsFilter extends Filter { public class PlayerFlyoutMenuItemsFilter extends Filter {
@@ -20,17 +20,9 @@ public class PlayerFlyoutMenuItemsFilter extends Filter {
} }
private final ByteArrayFilterGroupList flyoutFilterGroupList = new ByteArrayFilterGroupList(); private final ByteArrayFilterGroupList flyoutFilterGroupList = new ByteArrayFilterGroupList();
private final ByteArrayFilterGroup exception;
private final StringFilterGroup videoQualityMenuFooter; private final StringFilterGroup videoQualityMenuFooter;
public PlayerFlyoutMenuItemsFilter() { public PlayerFlyoutMenuItemsFilter() {
exception = new ByteArrayFilterGroup(
// Whitelist Quality menu item when "Hide Additional settings menu" is enabled
Settings.HIDE_PLAYER_FLYOUT_ADDITIONAL_SETTINGS,
"quality_sheet"
);
videoQualityMenuFooter = new StringFilterGroup( videoQualityMenuFooter = new StringFilterGroup(
Settings.HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER, Settings.HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER,
"quality_sheet_footer" "quality_sheet_footer"
@@ -44,11 +36,11 @@ public class PlayerFlyoutMenuItemsFilter extends Filter {
flyoutFilterGroupList.addAll( flyoutFilterGroupList.addAll(
new ByteArrayFilterGroup( new ByteArrayFilterGroup(
Settings.HIDE_PLAYER_FLYOUT_CAPTIONS, Settings.HIDE_PLAYER_FLYOUT_CAPTIONS,
"closed_caption" "closed_caption_"
), ),
new ByteArrayFilterGroup( new ByteArrayFilterGroup(
Settings.HIDE_PLAYER_FLYOUT_ADDITIONAL_SETTINGS, Settings.HIDE_PLAYER_FLYOUT_ADDITIONAL_SETTINGS,
"yt_outline_gear" "yt_outline_gear_"
), ),
new ByteArrayFilterGroup( new ByteArrayFilterGroup(
Settings.HIDE_PLAYER_FLYOUT_LOOP_VIDEO, Settings.HIDE_PLAYER_FLYOUT_LOOP_VIDEO,
@@ -56,31 +48,31 @@ public class PlayerFlyoutMenuItemsFilter extends Filter {
), ),
new ByteArrayFilterGroup( new ByteArrayFilterGroup(
Settings.HIDE_PLAYER_FLYOUT_AMBIENT_MODE, Settings.HIDE_PLAYER_FLYOUT_AMBIENT_MODE,
"yt_outline_screen_light" "yt_outline_screen_light_"
), ),
new ByteArrayFilterGroup( new ByteArrayFilterGroup(
Settings.HIDE_PLAYER_FLYOUT_STABLE_VOLUME, Settings.HIDE_PLAYER_FLYOUT_STABLE_VOLUME,
"volume_stable" "volume_stable_"
), ),
new ByteArrayFilterGroup( new ByteArrayFilterGroup(
Settings.HIDE_PLAYER_FLYOUT_HELP, Settings.HIDE_PLAYER_FLYOUT_HELP,
"yt_outline_question_circle" "yt_outline_question_circle_"
), ),
new ByteArrayFilterGroup( new ByteArrayFilterGroup(
Settings.HIDE_PLAYER_FLYOUT_MORE_INFO, Settings.HIDE_PLAYER_FLYOUT_MORE_INFO,
"yt_outline_info_circle" "yt_outline_info_circle_"
), ),
new ByteArrayFilterGroup( new ByteArrayFilterGroup(
Settings.HIDE_PLAYER_FLYOUT_LOCK_SCREEN, Settings.HIDE_PLAYER_FLYOUT_LOCK_SCREEN,
"yt_outline_lock" "yt_outline_lock_"
), ),
new ByteArrayFilterGroup( new ByteArrayFilterGroup(
Settings.HIDE_PLAYER_FLYOUT_SPEED, Settings.HIDE_PLAYER_FLYOUT_SPEED,
"yt_outline_play_arrow_half_circle" "yt_outline_play_arrow_half_circle_"
), ),
new ByteArrayFilterGroup( new ByteArrayFilterGroup(
Settings.HIDE_PLAYER_FLYOUT_AUDIO_TRACK, Settings.HIDE_PLAYER_FLYOUT_AUDIO_TRACK,
"yt_outline_person_radar" "yt_outline_person_radar_"
), ),
new ByteArrayFilterGroup( new ByteArrayFilterGroup(
Settings.HIDE_PLAYER_FLYOUT_SLEEP_TIMER, Settings.HIDE_PLAYER_FLYOUT_SLEEP_TIMER,
@@ -88,7 +80,11 @@ public class PlayerFlyoutMenuItemsFilter extends Filter {
), ),
new ByteArrayFilterGroup( new ByteArrayFilterGroup(
Settings.HIDE_PLAYER_FLYOUT_WATCH_IN_VR, Settings.HIDE_PLAYER_FLYOUT_WATCH_IN_VR,
"yt_outline_vr" "yt_outline_vr_"
),
new ByteArrayFilterGroup(
Settings.HIDE_PLAYER_FLYOUT_VIDEO_QUALITY,
"yt_outline_adjust_"
) )
); );
} }
@@ -105,7 +101,7 @@ public class PlayerFlyoutMenuItemsFilter extends Filter {
} }
// Shorts also use this player flyout panel // Shorts also use this player flyout panel
if (PlayerType.getCurrent().isNoneOrHidden() || exception.check(buffer).isFiltered()) { if (ShortsPlayerState.isOpen()) {
return false; return false;
} }

View File

@@ -3,13 +3,8 @@ package app.revanced.extension.youtube.patches.playback.quality;
import static app.revanced.extension.shared.StringRef.str; import static app.revanced.extension.shared.StringRef.str;
import static app.revanced.extension.shared.Utils.NetworkType; import static app.revanced.extension.shared.Utils.NetworkType;
import androidx.annotation.Nullable;
import com.google.android.libraries.youtube.innertube.model.media.VideoQuality; import com.google.android.libraries.youtube.innertube.model.media.VideoQuality;
import java.util.Arrays;
import java.util.List;
import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils; import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BooleanSetting; import app.revanced.extension.shared.settings.BooleanSetting;
@@ -17,69 +12,15 @@ import app.revanced.extension.shared.settings.IntegerSetting;
import app.revanced.extension.youtube.patches.VideoInformation; import app.revanced.extension.youtube.patches.VideoInformation;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.ShortsPlayerState; import app.revanced.extension.youtube.shared.ShortsPlayerState;
import app.revanced.extension.youtube.videoplayer.VideoQualityDialogButton;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class RememberVideoQualityPatch { public class RememberVideoQualityPatch {
/**
* Interface to use obfuscated methods.
*/
public interface VideoQualityMenuInterface {
void patch_setQuality(VideoQuality quality);
}
/**
* Video resolution of the automatic quality option..
*/
public static final int AUTOMATIC_VIDEO_QUALITY_VALUE = -2;
/**
* All quality names are the same for all languages.
* VideoQuality also has a resolution enum that can be used if needed.
*/
public static final String VIDEO_QUALITY_1080P_PREMIUM_NAME = "1080p Premium";
private static final IntegerSetting videoQualityWifi = Settings.VIDEO_QUALITY_DEFAULT_WIFI; private static final IntegerSetting videoQualityWifi = Settings.VIDEO_QUALITY_DEFAULT_WIFI;
private static final IntegerSetting videoQualityMobile = Settings.VIDEO_QUALITY_DEFAULT_MOBILE; private static final IntegerSetting videoQualityMobile = Settings.VIDEO_QUALITY_DEFAULT_MOBILE;
private static final IntegerSetting shortsQualityWifi = Settings.SHORTS_QUALITY_DEFAULT_WIFI; private static final IntegerSetting shortsQualityWifi = Settings.SHORTS_QUALITY_DEFAULT_WIFI;
private static final IntegerSetting shortsQualityMobile = Settings.SHORTS_QUALITY_DEFAULT_MOBILE; private static final IntegerSetting shortsQualityMobile = Settings.SHORTS_QUALITY_DEFAULT_MOBILE;
private static boolean qualityNeedsUpdating;
/**
* The available qualities of the current video.
*/
@Nullable
private static List<VideoQuality> currentQualities;
/**
* The current quality of the video playing.
* This is always the actual quality even if Automatic quality is active.
*/
@Nullable
private static VideoQuality currentQuality;
/**
* The current VideoQualityMenuInterface, set during setVideoQuality.
*/
@Nullable
private static VideoQualityMenuInterface currentMenuInterface;
@Nullable
public static List<VideoQuality> getCurrentQualities() {
return currentQualities;
}
@Nullable
public static VideoQuality getCurrentQuality() {
return currentQuality;
}
@Nullable
public static VideoQualityMenuInterface getCurrentMenuInterface() {
return currentMenuInterface;
}
public static boolean shouldRememberVideoQuality() { public static boolean shouldRememberVideoQuality() {
BooleanSetting preference = ShortsPlayerState.isOpen() BooleanSetting preference = ShortsPlayerState.isOpen()
@@ -129,91 +70,17 @@ public class RememberVideoQualityPatch {
/** /**
* Injection point. * Injection point.
* * @param userSelectedQualityIndex Element index of {@link VideoInformation#getCurrentQualities()}.
* @param qualities Video qualities available, ordered from largest to smallest, with index 0 being the 'automatic' value of -2
* @param originalQualityIndex quality index to use, as chosen by YouTube
*/
public static int setVideoQuality(VideoQuality[] qualities, VideoQualityMenuInterface menu, int originalQualityIndex) {
try {
Utils.verifyOnMainThread();
currentMenuInterface = menu;
final boolean availableQualitiesChanged = currentQualities == null
|| currentQualities.size() != qualities.length;
if (availableQualitiesChanged) {
currentQualities = Arrays.asList(qualities);
Logger.printDebug(() -> "VideoQualities: " + currentQualities);
}
VideoQuality updatedCurrentQuality = qualities[originalQualityIndex];
if (updatedCurrentQuality.patch_getResolution() != AUTOMATIC_VIDEO_QUALITY_VALUE &&
(currentQuality == null
|| !currentQuality.patch_getQualityName().equals(updatedCurrentQuality.patch_getQualityName()))) {
currentQuality = updatedCurrentQuality;
Logger.printDebug(() -> "Current quality changed to: " + updatedCurrentQuality);
VideoQualityDialogButton.updateButtonIcon(updatedCurrentQuality);
}
final int preferredQuality = getDefaultQualityResolution();
if (preferredQuality == AUTOMATIC_VIDEO_QUALITY_VALUE) {
return originalQualityIndex; // Nothing to do.
}
// After changing videos the qualities can initially be for the prior video.
// If the qualities have changed and the default is not auto then an update is needed.
if (!qualityNeedsUpdating && !availableQualitiesChanged) {
return originalQualityIndex;
}
qualityNeedsUpdating = false;
// Find the highest quality that is equal to or less than the preferred.
int i = 0;
for (VideoQuality quality : qualities) {
final int qualityResolution = quality.patch_getResolution();
if (qualityResolution != AUTOMATIC_VIDEO_QUALITY_VALUE && qualityResolution <= preferredQuality) {
final boolean qualityNeedsChange = (i != originalQualityIndex);
Logger.printDebug(() -> qualityNeedsChange
? "Changing video quality from: " + updatedCurrentQuality + " to: " + quality
: "Video is already the preferred quality: " + quality
);
// On first load of a new regular video, if the video is already the
// desired quality then the quality flyout will show 'Auto' (ie: Auto (720p)).
//
// To prevent user confusion, set the video index even if the
// quality is already correct so the UI picker will not display "Auto".
//
// Only change Shorts quality if the quality actually needs to change,
// because the "auto" option is not shown in the flyout
// and setting the same quality again can cause the Short to restart.
if (qualityNeedsChange || !ShortsPlayerState.isOpen()) {
menu.patch_setQuality(qualities[i]);
return i;
}
return originalQualityIndex;
}
i++;
}
} catch (Exception ex) {
Logger.printException(() -> "setVideoQuality failure", ex);
}
return originalQualityIndex;
}
/**
* Injection point.
* @param userSelectedQualityIndex Element index of {@link #currentQualities}.
*/ */
public static void userChangedShortsQuality(int userSelectedQualityIndex) { public static void userChangedShortsQuality(int userSelectedQualityIndex) {
try { try {
if (shouldRememberVideoQuality()) { if (shouldRememberVideoQuality()) {
VideoQuality[] currentQualities = VideoInformation.getCurrentQualities();
if (currentQualities == null) { if (currentQualities == null) {
Logger.printDebug(() -> "Cannot save default quality, qualities is null"); Logger.printDebug(() -> "Cannot save default quality, qualities is null");
return; return;
} }
VideoQuality quality = currentQualities.get(userSelectedQualityIndex); VideoQuality quality = currentQualities[userSelectedQualityIndex];
saveDefaultQuality(quality.patch_getResolution()); saveDefaultQuality(quality.patch_getResolution());
} }
} catch (Exception ex) { } catch (Exception ex) {
@@ -227,6 +94,7 @@ public class RememberVideoQualityPatch {
*/ */
public static void userChangedQuality(int videoResolution) { public static void userChangedQuality(int videoResolution) {
Utils.verifyOnMainThread(); Utils.verifyOnMainThread();
Logger.printDebug(() -> "User changed quality to: " + videoResolution);
if (shouldRememberVideoQuality()) { if (shouldRememberVideoQuality()) {
saveDefaultQuality(videoResolution); saveDefaultQuality(videoResolution);
@@ -237,27 +105,6 @@ public class RememberVideoQualityPatch {
* Injection point. * Injection point.
*/ */
public static void newVideoStarted(VideoInformation.PlaybackController ignoredPlayerController) { public static void newVideoStarted(VideoInformation.PlaybackController ignoredPlayerController) {
Utils.verifyOnMainThread(); VideoInformation.setDesiredVideoResolution(getDefaultQualityResolution());
Logger.printDebug(() -> "newVideoStarted");
currentQualities = null;
currentQuality = null;
currentMenuInterface = null;
qualityNeedsUpdating = true;
// Hide the quality button until playback starts and the qualities are available.
VideoQualityDialogButton.updateButtonIcon(null);
}
/**
* Injection point. Fixes bad data used by YouTube.
*/
public static int fixVideoQualityResolution(String name, int quality) {
final int correctQuality = 480;
if (name.equals("480p") && quality != correctQuality) {
return correctQuality;
}
return quality;
} }
} }

View File

@@ -100,7 +100,8 @@ public class CustomPlaybackSpeedPatch {
private static WeakReference<Dialog> currentDialog = new WeakReference<>(null); private static WeakReference<Dialog> currentDialog = new WeakReference<>(null);
static { static {
// Cap at 2 decimals (rounds automatically). // Use same 2 digit format as built in speed picker,
speedFormatter.setMinimumFractionDigits(2);
speedFormatter.setMaximumFractionDigits(2); speedFormatter.setMaximumFractionDigits(2);
final float holdSpeed = Settings.SPEED_TAP_AND_HOLD.get(); final float holdSpeed = Settings.SPEED_TAP_AND_HOLD.get();
@@ -321,7 +322,7 @@ public class CustomPlaybackSpeedPatch {
TextView currentSpeedText = new TextView(context); TextView currentSpeedText = new TextView(context);
float currentSpeed = VideoInformation.getPlaybackSpeed(); float currentSpeed = VideoInformation.getPlaybackSpeed();
// Initially show with only 0 minimum digits, so 1.0 shows as 1x // Initially show with only 0 minimum digits, so 1.0 shows as 1x
currentSpeedText.setText(formatSpeedStringX(currentSpeed, 0)); currentSpeedText.setText(formatSpeedStringX(currentSpeed));
currentSpeedText.setTextColor(Utils.getAppForegroundColor()); currentSpeedText.setTextColor(Utils.getAppForegroundColor());
currentSpeedText.setTextSize(16); currentSpeedText.setTextSize(16);
currentSpeedText.setTypeface(Typeface.DEFAULT_BOLD); currentSpeedText.setTypeface(Typeface.DEFAULT_BOLD);
@@ -398,10 +399,11 @@ public class CustomPlaybackSpeedPatch {
return null; return null;
} }
VideoInformation.overridePlaybackSpeed(roundedSpeed); currentSpeedText.setText(formatSpeedStringX(roundedSpeed)); // Update display.
RememberPlaybackSpeedPatch.userSelectedPlaybackSpeed(roundedSpeed);
currentSpeedText.setText(formatSpeedStringX(roundedSpeed, 2)); // Update display.
speedSlider.setProgress(speedToProgressValue(roundedSpeed)); // Update slider. speedSlider.setProgress(speedToProgressValue(roundedSpeed)); // Update slider.
RememberPlaybackSpeedPatch.userSelectedPlaybackSpeed(roundedSpeed);
VideoInformation.overridePlaybackSpeed(roundedSpeed);
return null; return null;
}; };
@@ -437,7 +439,7 @@ public class CustomPlaybackSpeedPatch {
gridParams.setMargins(0, 0, 0, 0); // No margins around GridLayout. gridParams.setMargins(0, 0, 0, 0); // No margins around GridLayout.
gridLayout.setLayoutParams(gridParams); gridLayout.setLayoutParams(gridParams);
// For all buttons show at least 1 zero in decimal (2 -> "2.0"). // For button use 1 digit minimum.
speedFormatter.setMinimumFractionDigits(1); speedFormatter.setMinimumFractionDigits(1);
// Add buttons for each preset playback speed. // Add buttons for each preset playback speed.
@@ -455,7 +457,7 @@ public class CustomPlaybackSpeedPatch {
// Create speed button. // Create speed button.
Button speedButton = new Button(context, null, 0); Button speedButton = new Button(context, null, 0);
speedButton.setText(speedFormatter.format(speed)); // Do not use 'x' speed format. speedButton.setText(speedFormatter.format(speed));
speedButton.setTextColor(Utils.getAppForegroundColor()); speedButton.setTextColor(Utils.getAppForegroundColor());
speedButton.setTextSize(12); speedButton.setTextSize(12);
speedButton.setAllCaps(false); speedButton.setAllCaps(false);
@@ -498,6 +500,9 @@ public class CustomPlaybackSpeedPatch {
gridLayout.addView(buttonContainer); gridLayout.addView(buttonContainer);
} }
// Restore 2 digit minimum.
speedFormatter.setMinimumFractionDigits(2);
// Add in-rows speed buttons layout to main layout. // Add in-rows speed buttons layout to main layout.
mainLayout.addView(gridLayout); mainLayout.addView(gridLayout);
@@ -631,8 +636,7 @@ public class CustomPlaybackSpeedPatch {
* @param speed The playback speed value to format. * @param speed The playback speed value to format.
* @return A string representation of the speed with 'x' (e.g. "1.25x" or "1.00x"). * @return A string representation of the speed with 'x' (e.g. "1.25x" or "1.00x").
*/ */
private static String formatSpeedStringX(float speed, int minimumFractionDigits) { private static String formatSpeedStringX(float speed) {
speedFormatter.setMinimumFractionDigits(minimumFractionDigits);
return speedFormatter.format(speed) + 'x'; return speedFormatter.format(speed) + 'x';
} }

View File

@@ -244,6 +244,7 @@ public class Settings extends BaseSettings {
public static final BooleanSetting HIDE_PLAYER_FLYOUT_SPEED = new BooleanSetting("revanced_hide_player_flyout_speed", FALSE); public static final BooleanSetting HIDE_PLAYER_FLYOUT_SPEED = new BooleanSetting("revanced_hide_player_flyout_speed", FALSE);
public static final BooleanSetting HIDE_PLAYER_FLYOUT_STABLE_VOLUME = new BooleanSetting("revanced_hide_player_flyout_stable_volume", FALSE); public static final BooleanSetting HIDE_PLAYER_FLYOUT_STABLE_VOLUME = new BooleanSetting("revanced_hide_player_flyout_stable_volume", FALSE);
public static final BooleanSetting HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER = new BooleanSetting("revanced_hide_player_flyout_video_quality_footer", FALSE); public static final BooleanSetting HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER = new BooleanSetting("revanced_hide_player_flyout_video_quality_footer", FALSE);
public static final BooleanSetting HIDE_PLAYER_FLYOUT_VIDEO_QUALITY = new BooleanSetting("revanced_hide_player_flyout_video_quality", FALSE);
public static final BooleanSetting HIDE_PLAYER_FLYOUT_WATCH_IN_VR = new BooleanSetting("revanced_hide_player_flyout_watch_in_vr", TRUE); public static final BooleanSetting HIDE_PLAYER_FLYOUT_WATCH_IN_VR = new BooleanSetting("revanced_hide_player_flyout_watch_in_vr", TRUE);
// General layout // General layout

View File

@@ -26,6 +26,7 @@ public class CreateSegmentButton {
controlsView, controlsView,
"revanced_sb_create_segment_button", "revanced_sb_create_segment_button",
null, null,
null,
CreateSegmentButton::shouldBeShown, CreateSegmentButton::shouldBeShown,
v -> SponsorBlockViewController.toggleNewSegmentLayoutVisibility(), v -> SponsorBlockViewController.toggleNewSegmentLayoutVisibility(),
null null

View File

@@ -28,6 +28,7 @@ public class VotingButton {
controlsView, controlsView,
"revanced_sb_voting_button", "revanced_sb_voting_button",
null, null,
null,
VotingButton::shouldBeShown, VotingButton::shouldBeShown,
v -> SponsorBlockUtils.onVotingClicked(v.getContext()), v -> SponsorBlockUtils.onVotingClicked(v.getContext()),
null null

View File

@@ -7,7 +7,6 @@ import androidx.annotation.Nullable;
import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Logger;
import app.revanced.extension.youtube.patches.CopyVideoUrlPatch; import app.revanced.extension.youtube.patches.CopyVideoUrlPatch;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.PlayerType;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class CopyVideoUrlButton { public class CopyVideoUrlButton {
@@ -23,6 +22,7 @@ public class CopyVideoUrlButton {
controlsView, controlsView,
"revanced_copy_video_url_button", "revanced_copy_video_url_button",
"revanced_copy_video_url_button_placeholder", "revanced_copy_video_url_button_placeholder",
null,
Settings.COPY_VIDEO_URL::get, Settings.COPY_VIDEO_URL::get,
view -> CopyVideoUrlPatch.copyUrl(false), view -> CopyVideoUrlPatch.copyUrl(false),
view -> { view -> {

View File

@@ -7,7 +7,6 @@ import androidx.annotation.Nullable;
import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Logger;
import app.revanced.extension.youtube.patches.CopyVideoUrlPatch; import app.revanced.extension.youtube.patches.CopyVideoUrlPatch;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.PlayerType;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class CopyVideoUrlTimestampButton { public class CopyVideoUrlTimestampButton {
@@ -23,6 +22,7 @@ public class CopyVideoUrlTimestampButton {
controlsView, controlsView,
"revanced_copy_video_url_timestamp_button", "revanced_copy_video_url_timestamp_button",
"revanced_copy_video_url_timestamp_button_placeholder", "revanced_copy_video_url_timestamp_button_placeholder",
null,
Settings.COPY_VIDEO_URL_TIMESTAMP::get, Settings.COPY_VIDEO_URL_TIMESTAMP::get,
view -> CopyVideoUrlPatch.copyUrl(true), view -> CopyVideoUrlPatch.copyUrl(true),
view -> { view -> {

View File

@@ -23,6 +23,7 @@ public class ExternalDownloadButton {
controlsView, controlsView,
"revanced_external_download_button", "revanced_external_download_button",
"revanced_external_download_button_placeholder", "revanced_external_download_button_placeholder",
null,
Settings.EXTERNAL_DOWNLOADER::get, Settings.EXTERNAL_DOWNLOADER::get,
ExternalDownloadButton::onDownloadClick, ExternalDownloadButton::onDownloadClick,
null null

View File

@@ -4,16 +4,26 @@ import android.view.View;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import java.text.DecimalFormat;
import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.patches.VideoInformation; import app.revanced.extension.youtube.patches.VideoInformation;
import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch; import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class PlaybackSpeedDialogButton { public class PlaybackSpeedDialogButton {
@Nullable @Nullable
private static PlayerControlButton instance; private static PlayerControlButton instance;
private static final DecimalFormat speedDecimalFormatter = new DecimalFormat();
static {
speedDecimalFormatter.setMinimumFractionDigits(1);
speedDecimalFormatter.setMaximumFractionDigits(2);
}
/** /**
* Injection point. * Injection point.
*/ */
@@ -21,8 +31,10 @@ public class PlaybackSpeedDialogButton {
try { try {
instance = new PlayerControlButton( instance = new PlayerControlButton(
controlsView, controlsView,
"revanced_playback_speed_dialog_button_container",
"revanced_playback_speed_dialog_button", "revanced_playback_speed_dialog_button",
"revanced_playback_speed_dialog_button_placeholder", "revanced_playback_speed_dialog_button_placeholder",
"revanced_playback_speed_dialog_button_text",
Settings.PLAYBACK_SPEED_DIALOG_BUTTON::get, Settings.PLAYBACK_SPEED_DIALOG_BUTTON::get,
view -> { view -> {
try { try {
@@ -37,11 +49,11 @@ public class PlaybackSpeedDialogButton {
}, },
view -> { view -> {
try { try {
final float defaultSpeed = Settings.PLAYBACK_SPEED_DEFAULT.get();
final float speed = (!Settings.REMEMBER_PLAYBACK_SPEED_LAST_SELECTED.get() || final float speed = (!Settings.REMEMBER_PLAYBACK_SPEED_LAST_SELECTED.get() ||
VideoInformation.getPlaybackSpeed() == Settings.PLAYBACK_SPEED_DEFAULT.get()) VideoInformation.getPlaybackSpeed() == defaultSpeed)
? 1.0f ? 1.0f
: Settings.PLAYBACK_SPEED_DEFAULT.get(); : defaultSpeed;
VideoInformation.overridePlaybackSpeed(speed); VideoInformation.overridePlaybackSpeed(speed);
} catch (Exception ex) { } catch (Exception ex) {
Logger.printException(() -> "speed button reset failure", ex); Logger.printException(() -> "speed button reset failure", ex);
@@ -49,22 +61,53 @@ public class PlaybackSpeedDialogButton {
return true; return true;
} }
); );
// Set the appropriate icon.
updateButtonAppearance();
} catch (Exception ex) { } catch (Exception ex) {
Logger.printException(() -> "initializeButton failure", ex); Logger.printException(() -> "initializeButton failure", ex);
} }
} }
/** /**
* injection point * Injection point.
*/ */
public static void setVisibilityImmediate(boolean visible) { public static void setVisibilityImmediate(boolean visible) {
if (instance != null) instance.setVisibilityImmediate(visible); if (instance != null) {
instance.setVisibilityImmediate(visible);
}
} }
/** /**
* injection point * Injection point.
*/ */
public static void setVisibility(boolean visible, boolean animated) { public static void setVisibility(boolean visible, boolean animated) {
if (instance != null) instance.setVisibility(visible, animated); if (instance != null) {
instance.setVisibility(visible, animated);
}
}
/**
* Injection point.
*/
public static void videoSpeedChanged(float currentVideoSpeed) {
updateButtonAppearance();
}
/**
* Updates the button's appearance, including icon and text overlay.
*/
private static void updateButtonAppearance() {
if (instance == null) return;
try {
Utils.verifyOnMainThread();
String speedText = speedDecimalFormatter.format(VideoInformation.getPlaybackSpeed());
instance.setTextOverlay(speedText);
Logger.printDebug(() -> "Updated playback speed button text to: " + speedText);
} catch (Exception ex) {
Logger.printException(() -> "updateButtonAppearance failure", ex);
}
} }
} }

View File

@@ -3,6 +3,7 @@ package app.revanced.extension.youtube.videoplayer;
import android.view.View; import android.view.View;
import android.view.animation.Animation; import android.view.animation.Animation;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@@ -14,11 +15,12 @@ import app.revanced.extension.youtube.shared.PlayerType;
import kotlin.Unit; import kotlin.Unit;
public class PlayerControlButton { public class PlayerControlButton {
public interface PlayerControlButtonVisibility {
public interface PlayerControlButtonStatus {
/** /**
* @return If the button should be shown when the player overlay is visible. * @return If the button should be shown when the player overlay is visible.
*/ */
boolean shouldBeShown(); boolean buttonEnabled();
} }
private static final int fadeInDuration; private static final int fadeInDuration;
@@ -44,23 +46,46 @@ public class PlayerControlButton {
fadeOutImmediate.setDuration(Utils.getResourceInteger("fade_duration_fast")); fadeOutImmediate.setDuration(Utils.getResourceInteger("fade_duration_fast"));
} }
private final WeakReference<View> containerRef;
private final WeakReference<View> buttonRef; private final WeakReference<View> buttonRef;
/** /**
* Empty view with the same layout size as the button. Used to fill empty space while the * Empty view with the same layout size as the button. Used to fill empty space while the
* fade out animation runs. Without this the chapter titles overlapping the button when fading out. * fade out animation runs. Without this the chapter titles overlapping the button when fading out.
*/ */
private final WeakReference<View> placeHolderRef; private final WeakReference<View> placeHolderRef;
private final PlayerControlButtonVisibility visibilityCheck; private final WeakReference<TextView> textOverlayRef;
private final PlayerControlButtonStatus enabledStatus;
private boolean isVisible; private boolean isVisible;
public PlayerControlButton(View controlsViewGroup, public PlayerControlButton(View controlsViewGroup,
String imageViewButtonId, String buttonId,
@Nullable String placeholderId, @Nullable String placeholderId,
PlayerControlButtonVisibility buttonVisibility, @Nullable String textOverlayId,
PlayerControlButtonStatus enabledStatus,
View.OnClickListener onClickListener, View.OnClickListener onClickListener,
@Nullable View.OnLongClickListener longClickListener) { @Nullable View.OnLongClickListener longClickListener) {
ImageView imageView = Utils.getChildViewByResourceName(controlsViewGroup, imageViewButtonId); this(controlsViewGroup, buttonId, buttonId, placeholderId, textOverlayId,
imageView.setVisibility(View.GONE); enabledStatus, onClickListener, longClickListener);
}
public PlayerControlButton(View controlsViewGroup,
String viewToHide,
String buttonId,
@Nullable String placeholderId,
@Nullable String textOverlayId,
PlayerControlButtonStatus enabledStatus,
View.OnClickListener onClickListener,
@Nullable View.OnLongClickListener longClickListener) {
View containerView = Utils.getChildViewByResourceName(controlsViewGroup, viewToHide);
containerView.setVisibility(View.GONE);
containerRef = new WeakReference<>(containerView);
View button = Utils.getChildViewByResourceName(controlsViewGroup, buttonId);
button.setOnClickListener(onClickListener);
if (longClickListener != null) {
button.setOnLongClickListener(longClickListener);
}
buttonRef = new WeakReference<>(button);
View tempPlaceholder = null; View tempPlaceholder = null;
if (placeholderId != null) { if (placeholderId != null) {
@@ -69,19 +94,19 @@ public class PlayerControlButton {
} }
placeHolderRef = new WeakReference<>(tempPlaceholder); placeHolderRef = new WeakReference<>(tempPlaceholder);
imageView.setOnClickListener(onClickListener); TextView tempTextOverlay = null;
if (longClickListener != null) { if (textOverlayId != null) {
imageView.setOnLongClickListener(longClickListener); tempTextOverlay = Utils.getChildViewByResourceName(controlsViewGroup, textOverlayId);
} }
textOverlayRef = new WeakReference<>(tempTextOverlay);
visibilityCheck = buttonVisibility; this.enabledStatus = enabledStatus;
buttonRef = new WeakReference<>(imageView);
isVisible = false; isVisible = false;
// Update the visibility after the player type changes. // Update the visibility after the player type changes.
// This ensures that button animations are cleared and their states are updated correctly // This ensures that button animations are cleared and their states are updated correctly
// when switching between states like minimized, maximized, or fullscreen, preventing // when switching between states like minimized, maximized, or fullscreen, preventing
// "stuck" animations or incorrect visibility. Without this fix the issue is most noticable // "stuck" animations or incorrect visibility. Without this fix the issue is most noticeable
// when maximizing type 3 miniplayer. // when maximizing type 3 miniplayer.
PlayerType.getOnChange().addObserver((PlayerType type) -> { PlayerType.getOnChange().addObserver((PlayerType type) -> {
playerTypeChanged(type); playerTypeChanged(type);
@@ -111,33 +136,33 @@ public class PlayerControlButton {
if (isVisible == visible) return; if (isVisible == visible) return;
isVisible = visible; isVisible = visible;
View button = buttonRef.get(); View container = containerRef.get();
if (button == null) return; if (container == null) return;
View placeholder = placeHolderRef.get(); View placeholder = placeHolderRef.get();
final boolean shouldBeShown = visibilityCheck.shouldBeShown(); final boolean buttonEnabled = enabledStatus.buttonEnabled();
if (visible && shouldBeShown) { if (visible && buttonEnabled) {
button.clearAnimation(); container.clearAnimation();
if (animated) { if (animated) {
button.startAnimation(PlayerControlButton.fadeInAnimation); container.startAnimation(fadeInAnimation);
} }
button.setVisibility(View.VISIBLE); container.setVisibility(View.VISIBLE);
if (placeholder != null) { if (placeholder != null) {
placeholder.setVisibility(View.GONE); placeholder.setVisibility(View.GONE);
} }
} else { } else {
if (button.getVisibility() == View.VISIBLE) { if (container.getVisibility() == View.VISIBLE) {
button.clearAnimation(); container.clearAnimation();
if (animated) { if (animated) {
button.startAnimation(PlayerControlButton.fadeOutAnimation); container.startAnimation(fadeOutAnimation);
} }
button.setVisibility(View.GONE); container.setVisibility(View.GONE);
} }
if (placeholder != null) { if (placeholder != null) {
placeholder.setVisibility(shouldBeShown placeholder.setVisibility(buttonEnabled
? View.VISIBLE ? View.VISIBLE
: View.GONE); : View.GONE);
} }
@@ -155,36 +180,37 @@ public class PlayerControlButton {
return; return;
} }
View button = buttonRef.get(); View container = containerRef.get();
if (button == null) return; if (container == null) return;
button.clearAnimation(); container.clearAnimation();
View placeholder = placeHolderRef.get(); View placeholder = placeHolderRef.get();
if (visibilityCheck.shouldBeShown()) { if (enabledStatus.buttonEnabled()) {
if (isVisible) { if (isVisible) {
button.setVisibility(View.VISIBLE); container.setVisibility(View.VISIBLE);
if (placeholder != null) placeholder.setVisibility(View.GONE); if (placeholder != null) placeholder.setVisibility(View.GONE);
} else { } else {
button.setVisibility(View.GONE); container.setVisibility(View.GONE);
if (placeholder != null) placeholder.setVisibility(View.VISIBLE); if (placeholder != null) placeholder.setVisibility(View.VISIBLE);
} }
} else { } else {
button.setVisibility(View.GONE); container.setVisibility(View.GONE);
if (placeholder != null) placeholder.setVisibility(View.GONE); if (placeholder != null) placeholder.setVisibility(View.GONE);
} }
} }
public void hide() { public void hide() {
Utils.verifyOnMainThread();
if (!isVisible) return; if (!isVisible) return;
Utils.verifyOnMainThread(); View view = containerRef.get();
View view = buttonRef.get();
if (view == null) return; if (view == null) return;
view.setVisibility(View.GONE); view.setVisibility(View.GONE);
view = placeHolderRef.get(); View placeHolder = placeHolderRef.get();
if (view != null) view.setVisibility(View.GONE); if (placeHolder != null) view.setVisibility(View.GONE);
isVisible = false; isVisible = false;
} }
@@ -193,50 +219,20 @@ public class PlayerControlButton {
* @param resourceId Drawable identifier, or zero to hide the icon. * @param resourceId Drawable identifier, or zero to hide the icon.
*/ */
public void setIcon(int resourceId) { public void setIcon(int resourceId) {
try { View button = buttonRef.get();
View button = buttonRef.get(); if (button instanceof ImageView imageButton) {
if (button instanceof ImageView imageButton) { imageButton.setImageResource(resourceId);
imageButton.setImageResource(resourceId);
}
} catch (Exception ex) {
Logger.printException(() -> "setIcon failure", ex);
} }
} }
/** /**
* Starts an animation on the button. * Sets the text to be displayed on the text overlay.
* @param animation The animation to apply. * @param text The text to set on the overlay, or null to clear the text.
*/ */
public void startAnimation(Animation animation) { public void setTextOverlay(CharSequence text) {
try { TextView textOverlay = textOverlayRef.get();
View button = buttonRef.get(); if (textOverlay != null) {
if (button != null) { textOverlay.setText(text);
button.startAnimation(animation);
}
} catch (Exception ex) {
Logger.printException(() -> "startAnimation failure", ex);
} }
} }
/**
* Clears any animation on the button.
*/
public void clearAnimation() {
try {
View button = buttonRef.get();
if (button != null) {
button.clearAnimation();
}
} catch (Exception ex) {
Logger.printException(() -> "clearAnimation failure", ex);
}
}
/**
* Returns the View associated with this button.
* @return The button View.
*/
public View getView() {
return buttonRef.get();
}
} }

View File

@@ -2,9 +2,8 @@ package app.revanced.extension.youtube.videoplayer;
import static app.revanced.extension.shared.StringRef.str; import static app.revanced.extension.shared.StringRef.str;
import static app.revanced.extension.shared.Utils.dipToPixels; import static app.revanced.extension.shared.Utils.dipToPixels;
import static app.revanced.extension.youtube.patches.playback.quality.RememberVideoQualityPatch.AUTOMATIC_VIDEO_QUALITY_VALUE; import static app.revanced.extension.youtube.patches.VideoInformation.AUTOMATIC_VIDEO_QUALITY_VALUE;
import static app.revanced.extension.youtube.patches.playback.quality.RememberVideoQualityPatch.VIDEO_QUALITY_1080P_PREMIUM_NAME; import static app.revanced.extension.youtube.patches.VideoInformation.VIDEO_QUALITY_PREMIUM_NAME;
import static app.revanced.extension.youtube.patches.playback.quality.RememberVideoQualityPatch.VideoQualityMenuInterface;
import android.app.Dialog; import android.app.Dialog;
import android.content.Context; import android.content.Context;
@@ -14,6 +13,7 @@ import android.graphics.drawable.shapes.RoundRectShape;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import android.text.style.UnderlineSpan;
import android.view.Gravity; import android.view.Gravity;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MotionEvent; import android.view.MotionEvent;
@@ -39,73 +39,25 @@ import java.util.List;
import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils; import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.patches.VideoInformation;
import app.revanced.extension.youtube.patches.playback.quality.RememberVideoQualityPatch; import app.revanced.extension.youtube.patches.playback.quality.RememberVideoQualityPatch;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
import kotlin.Unit;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class VideoQualityDialogButton { public class VideoQualityDialogButton {
private static final int DRAWABLE_LD = getDrawableIdentifier("revanced_video_quality_dialog_button_ld");
private static final int DRAWABLE_SD = getDrawableIdentifier("revanced_video_quality_dialog_button_sd");
private static final int DRAWABLE_HD = getDrawableIdentifier("revanced_video_quality_dialog_button_hd");
private static final int DRAWABLE_FHD = getDrawableIdentifier("revanced_video_quality_dialog_button_fhd");
private static final int DRAWABLE_FHD_PLUS = getDrawableIdentifier("revanced_video_quality_dialog_button_fhd_plus");
private static final int DRAWABLE_QHD = getDrawableIdentifier("revanced_video_quality_dialog_button_qhd");
private static final int DRAWABLE_4K = getDrawableIdentifier("revanced_video_quality_dialog_button_4k");
private static final int DRAWABLE_UNKNOWN = getDrawableIdentifier("revanced_video_quality_dialog_button_unknown");
@Nullable @Nullable
private static PlayerControlButton instance; private static PlayerControlButton instance;
/** @Nullable
* The current resource name of the button icon. private static CharSequence currentOverlayText;
*/
private static int currentIconResource;
private static int getDrawableIdentifier(String resourceName) { static {
final int resourceId = Utils.getResourceIdentifier(resourceName, "drawable"); VideoInformation.onQualityChange.addObserver((@Nullable VideoQuality quality) -> {
if (resourceId == 0) Logger.printException(() -> "Could not find resource: " + resourceName); updateButtonText(quality);
return resourceId; return Unit.INSTANCE;
} });
/**
* Updates the button icon based on the current video quality.
*/
public static void updateButtonIcon(@Nullable VideoQuality quality) {
try {
Utils.verifyOnMainThread();
if (instance == null) return;
final int resolution = quality == null
? AUTOMATIC_VIDEO_QUALITY_VALUE // Video is still loading.
: quality.patch_getResolution();
final int iconResource = switch (resolution) {
case 144, 240, 360 -> DRAWABLE_LD;
case 480 -> DRAWABLE_SD;
case 720 -> DRAWABLE_HD;
case 1080 -> VIDEO_QUALITY_1080P_PREMIUM_NAME.equals(quality.patch_getQualityName())
? DRAWABLE_FHD_PLUS
: DRAWABLE_FHD;
case 1440 -> DRAWABLE_QHD;
case 2160 -> DRAWABLE_4K;
default -> DRAWABLE_UNKNOWN;
};
if (iconResource != currentIconResource) {
currentIconResource = iconResource;
Utils.runOnMainThreadDelayed(() -> {
if (iconResource != currentIconResource) {
Logger.printDebug(() -> "Ignoring stale button update to: " + quality);
return;
}
instance.setIcon(iconResource);
}, 100);
}
} catch (Exception ex) {
Logger.printException(() -> "updateButtonIcon failure", ex);
}
} }
/** /**
@@ -115,8 +67,10 @@ public class VideoQualityDialogButton {
try { try {
instance = new PlayerControlButton( instance = new PlayerControlButton(
controlsView, controlsView,
"revanced_video_quality_dialog_button_container",
"revanced_video_quality_dialog_button", "revanced_video_quality_dialog_button",
"revanced_video_quality_dialog_button_placeholder", "revanced_video_quality_dialog_button_placeholder",
"revanced_video_quality_dialog_button_text",
Settings.VIDEO_QUALITY_DIALOG_BUTTON::get, Settings.VIDEO_QUALITY_DIALOG_BUTTON::get,
view -> { view -> {
try { try {
@@ -127,9 +81,8 @@ public class VideoQualityDialogButton {
}, },
view -> { view -> {
try { try {
List<VideoQuality> qualities = RememberVideoQualityPatch.getCurrentQualities(); VideoQuality[] qualities = VideoInformation.getCurrentQualities();
VideoQualityMenuInterface menu = RememberVideoQualityPatch.getCurrentMenuInterface(); if (qualities == null) {
if (qualities == null || menu == null) {
Logger.printDebug(() -> "Cannot reset quality, videoQualities is null"); Logger.printDebug(() -> "Cannot reset quality, videoQualities is null");
return true; return true;
} }
@@ -140,7 +93,7 @@ public class VideoQualityDialogButton {
final int resolution = quality.patch_getResolution(); final int resolution = quality.patch_getResolution();
if (resolution != AUTOMATIC_VIDEO_QUALITY_VALUE && resolution <= defaultResolution) { if (resolution != AUTOMATIC_VIDEO_QUALITY_VALUE && resolution <= defaultResolution) {
Logger.printDebug(() -> "Resetting quality to: " + quality); Logger.printDebug(() -> "Resetting quality to: " + quality);
menu.patch_setQuality(quality); VideoInformation.changeQuality(quality);
return true; return true;
} }
} }
@@ -156,8 +109,8 @@ public class VideoQualityDialogButton {
} }
); );
// Set initial icon. // Set initial text.
updateButtonIcon(RememberVideoQualityPatch.getCurrentQuality()); updateButtonText(VideoInformation.getCurrentQuality());
} catch (Exception ex) { } catch (Exception ex) {
Logger.printException(() -> "initializeButton failure", ex); Logger.printException(() -> "initializeButton failure", ex);
} }
@@ -181,33 +134,76 @@ public class VideoQualityDialogButton {
} }
} }
/**
* Updates the button text based on the current video quality.
*/
public static void updateButtonText(@Nullable VideoQuality quality) {
try {
Utils.verifyOnMainThread();
if (instance == null) return;
final int resolution = quality == null
? AUTOMATIC_VIDEO_QUALITY_VALUE // Video is still loading.
: quality.patch_getResolution();
SpannableStringBuilder text = new SpannableStringBuilder();
String qualityText = switch (resolution) {
case AUTOMATIC_VIDEO_QUALITY_VALUE -> "";
case 144, 240, 360 -> "LD";
case 480 -> "SD";
case 720 -> "HD";
case 1080 -> "FHD";
case 1440 -> "QHD";
case 2160 -> "4K";
default -> "?"; // Should never happen.
};
text.append(qualityText);
if (quality != null && quality.patch_getQualityName().contains(VIDEO_QUALITY_PREMIUM_NAME)) {
// Underline the entire "FHD" text for 1080p Premium.
text.setSpan(new UnderlineSpan(), 0, qualityText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
currentOverlayText = text;
Utils.runOnMainThreadDelayed(() -> {
if (currentOverlayText != text) {
Logger.printDebug(() -> "Ignoring stale button text update of: " + text);
return;
}
instance.setTextOverlay(text);
}, 100);
} catch (Exception ex) {
Logger.printException(() -> "updateButtonText failure", ex);
}
}
/** /**
* Shows a dialog with available video qualities, excluding Auto, with a title showing the current quality. * Shows a dialog with available video qualities, excluding Auto, with a title showing the current quality.
*/ */
private static void showVideoQualityDialog(Context context) { private static void showVideoQualityDialog(Context context) {
try { try {
List<VideoQuality> currentQualities = RememberVideoQualityPatch.getCurrentQualities(); VideoQuality[] currentQualities = VideoInformation.getCurrentQualities();
VideoQuality currentQuality = RememberVideoQualityPatch.getCurrentQuality(); VideoQuality currentQuality = VideoInformation.getCurrentQuality();
if (currentQualities == null || currentQuality == null) { if (currentQualities == null || currentQuality == null) {
Logger.printDebug(() -> "Cannot show qualities dialog, videoQualities is null"); Logger.printDebug(() -> "Cannot show qualities dialog, videoQualities is null");
return; return;
} }
if (currentQualities.size() < 2) { if (currentQualities.length < 2) {
// Should never happen. // Should never happen.
Logger.printException(() -> "Cannot show qualities dialog, no qualities available"); Logger.printException(() -> "Cannot show qualities dialog, no qualities available");
return; return;
} }
VideoQualityMenuInterface menu = RememberVideoQualityPatch.getCurrentMenuInterface(); // -1 adjustment for automatic quality at first index.
if (menu == null) { int listViewSelectedIndex = -1;
Logger.printDebug(() -> "Cannot show qualities dialog, menu is null"); for (VideoQuality quality : currentQualities) {
return; if (quality.patch_getQualityName().equals(currentQuality.patch_getQualityName())) {
break;
}
listViewSelectedIndex++;
} }
// -1 adjustment for automatic quality at first index. List<String> qualityLabels = new ArrayList<>(currentQualities.length - 1);
final int listViewSelectedIndex = currentQualities.indexOf(currentQuality) - 1;
List<String> qualityLabels = new ArrayList<>(currentQualities.size() - 1);
for (VideoQuality availableQuality : currentQualities) { for (VideoQuality availableQuality : currentQualities) {
if (availableQuality.patch_getResolution() != AUTOMATIC_VIDEO_QUALITY_VALUE) { if (availableQuality.patch_getResolution() != AUTOMATIC_VIDEO_QUALITY_VALUE) {
qualityLabels.add(availableQuality.patch_getQualityName()); qualityLabels.add(availableQuality.patch_getQualityName());
@@ -310,16 +306,9 @@ public class VideoQualityDialogButton {
listView.setOnItemClickListener((parent, view, which, id) -> { listView.setOnItemClickListener((parent, view, which, id) -> {
try { try {
final int originalIndex = which + 1; // Adjust for automatic. final int originalIndex = which + 1; // Adjust for automatic.
VideoQuality selectedQuality = currentQualities.get(originalIndex); VideoQuality selectedQuality = currentQualities[originalIndex];
Logger.printDebug(() -> "User clicked on quality: " + selectedQuality); RememberVideoQualityPatch.userChangedQuality(selectedQuality.patch_getResolution());
VideoInformation.changeQuality(selectedQuality);
if (RememberVideoQualityPatch.shouldRememberVideoQuality()) {
RememberVideoQualityPatch.saveDefaultQuality(selectedQuality.patch_getResolution());
}
// Don't update button icon now. Icon will update when the actual
// quality is changed by YT. This is needed to ensure the icon is correct
// if YT ignores changing from 1080p Premium to regular 1080p.
menu.patch_setQuality(selectedQuality);
dialog.dismiss(); dialog.dismiss();
} catch (Exception ex) { } catch (Exception ex) {
@@ -350,9 +339,12 @@ public class VideoQualityDialogButton {
portraitWidth = Math.min( portraitWidth = Math.min(
portraitWidth, portraitWidth,
context.getResources().getDisplayMetrics().heightPixels); context.getResources().getDisplayMetrics().heightPixels);
// Limit height in landscape mode.
params.height = Utils.percentageHeightToPixels(80);
} else {
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
} }
params.width = portraitWidth; params.width = portraitWidth;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(params); window.setAttributes(params);
window.setBackgroundDrawable(null); window.setBackgroundDrawable(null);
} }
@@ -422,6 +414,15 @@ public class VideoQualityDialogButton {
} }
private static class CustomQualityAdapter extends ArrayAdapter<String> { private static class CustomQualityAdapter extends ArrayAdapter<String> {
private static final int CUSTOM_LIST_ITEM_CHECKED_ID = Utils.getResourceIdentifier(
"revanced_custom_list_item_checked", "layout");
private static final int CHECK_ICON_ID = Utils.getResourceIdentifier(
"revanced_check_icon", "id");
private static final int CHECK_ICON_PLACEHOLDER_ID = Utils.getResourceIdentifier(
"revanced_check_icon_placeholder", "id");
private static final int ITEM_TEXT_ID = Utils.getResourceIdentifier(
"revanced_item_text", "id");
private int selectedPosition = -1; private int selectedPosition = -1;
public CustomQualityAdapter(@NonNull Context context, @NonNull List<String> objects) { public CustomQualityAdapter(@NonNull Context context, @NonNull List<String> objects) {
@@ -440,20 +441,14 @@ public class VideoQualityDialogButton {
if (convertView == null) { if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate( convertView = LayoutInflater.from(getContext()).inflate(
Utils.getResourceIdentifier("revanced_custom_list_item_checked", "layout"), CUSTOM_LIST_ITEM_CHECKED_ID,
parent, parent,
false false
); );
viewHolder = new ViewHolder(); viewHolder = new ViewHolder();
viewHolder.checkIcon = convertView.findViewById( viewHolder.checkIcon = convertView.findViewById(CHECK_ICON_ID);
Utils.getResourceIdentifier("revanced_check_icon", "id") viewHolder.placeholder = convertView.findViewById(CHECK_ICON_PLACEHOLDER_ID);
); viewHolder.textView = convertView.findViewById(ITEM_TEXT_ID);
viewHolder.placeholder = convertView.findViewById(
Utils.getResourceIdentifier("revanced_check_icon_placeholder", "id")
);
viewHolder.textView = convertView.findViewById(
Utils.getResourceIdentifier("revanced_item_text", "id")
);
convertView.setTag(viewHolder); convertView.setTag(viewHolder);
} else { } else {
viewHolder = (ViewHolder) convertView.getTag(); viewHolder = (ViewHolder) convertView.getTag();

View File

@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
org.gradle.parallel = true org.gradle.parallel = true
android.useAndroidX = true android.useAndroidX = true
kotlin.code.style = official kotlin.code.style = official
version = 5.33.0-dev.8 version = 5.34.0-dev.7

View File

@@ -1660,12 +1660,12 @@ public final class app/revanced/patches/youtube/video/quality/RememberVideoQuali
public static final fun getRememberVideoQualityPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getRememberVideoQualityPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
} }
public final class app/revanced/patches/youtube/video/quality/VideoQualityPatchKt { public final class app/revanced/patches/youtube/video/quality/VideoQualityDialogButtonPatchKt {
public static final fun getVideoQualityPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getVideoQualityDialogButtonPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
} }
public final class app/revanced/patches/youtube/video/quality/button/VideoQualityDialogButtonPatchKt { public final class app/revanced/patches/youtube/video/quality/VideoQualityPatchKt {
public static final fun getVideoQualityButtonPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getVideoQualityPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
} }
public final class app/revanced/patches/youtube/video/speed/PlaybackSpeedPatchKt { public final class app/revanced/patches/youtube/video/speed/PlaybackSpeedPatchKt {

View File

@@ -3,6 +3,7 @@ package app.revanced.patches.backdrops.misc.pro
import app.revanced.patcher.fingerprint import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
@Deprecated("Fingerprint no longer resolves and will soon be deleted.")
internal val proUnlockFingerprint = fingerprint { internal val proUnlockFingerprint = fingerprint {
opcodes( opcodes(
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,

View File

@@ -6,9 +6,8 @@ import app.revanced.patcher.patch.bytecodePatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Suppress("unused") @Suppress("unused")
val proUnlockPatch = bytecodePatch( @Deprecated("This patch no longer works and will soon be deleted.")
name = "Pro unlock", val proUnlockPatch = bytecodePatch{
) {
compatibleWith("com.backdrops.wallpapers") compatibleWith("com.backdrops.wallpapers")
execute { execute {

View File

@@ -8,7 +8,7 @@ val signatureCheckPatch = bytecodePatch(
name = "Disable signature check", name = "Disable signature check",
description = "Disables the signature check that causes the app to crash on startup." description = "Disables the signature check that causes the app to crash on startup."
) { ) {
compatibleWith("com.instagram.android"("378.0.0.52.68")) compatibleWith("com.instagram.android")
execute { execute {
isValidSignatureMethodFingerprint isValidSignatureMethodFingerprint

View File

@@ -5,6 +5,5 @@ import app.revanced.patcher.fingerprint
internal val isFacebookButtonEnabledFingerprint = fingerprint { internal val isFacebookButtonEnabledFingerprint = fingerprint {
parameters() parameters()
returns("Z") returns("Z")
strings("com.facebook.messaging.inbox.tab.plugins.core.tabtoolbarbutton." + strings("FacebookButtonTabButtonImplementation")
"facebookbutton.facebooktoolbarbutton.FacebookButtonTabButtonImplementation")
} }

View File

@@ -3,6 +3,7 @@ package app.revanced.patches.music.layout.compactheader
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.util.findFreeRegister
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Suppress("unused") @Suppress("unused")
@@ -17,13 +18,14 @@ val hideCategoryBar = bytecodePatch(
constructCategoryBarFingerprint.method.apply { constructCategoryBarFingerprint.method.apply {
val insertIndex = constructCategoryBarFingerprint.patternMatch!!.startIndex val insertIndex = constructCategoryBarFingerprint.patternMatch!!.startIndex
val register = getInstruction<OneRegisterInstruction>(insertIndex - 1).registerA val register = getInstruction<OneRegisterInstruction>(insertIndex - 1).registerA
val freeRegister = findFreeRegister(insertIndex, register)
addInstructions( addInstructions(
insertIndex, insertIndex,
""" """
const/16 v2, 0x8 const/16 v$freeRegister, 0x8
invoke-virtual {v$register, v2}, Landroid/view/View;->setVisibility(I)V invoke-virtual { v$register, v$freeRegister }, Landroid/view/View;->setVisibility(I)V
""", """
) )
} }
} }

View File

@@ -1,21 +1,15 @@
package app.revanced.patches.pixiv.ads package app.revanced.patches.pixiv.ads
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.util.returnEarly
@Suppress("unused") @Suppress("unused")
val hideAdsPatch = bytecodePatch( val hideAdsPatch = bytecodePatch(
name = "Hide ads", name = "Hide ads",
) { ) {
compatibleWith("jp.pxv.android") compatibleWith("jp.pxv.android"("6.141.1"))
execute { execute {
shouldShowAdsFingerprint.method.addInstructions( shouldShowAdsFingerprint.method.returnEarly(false)
0,
"""
const/4 v0, 0x0
return v0
""",
)
} }
} }

View File

@@ -21,7 +21,7 @@ val audioAdsPatch = bytecodePatch(
addResourcesPatch, addResourcesPatch,
) )
compatibleWith("tv.twitch.android.app") compatibleWith("tv.twitch.android.app"("16.9.1", "25.3.0"))
execute { execute {
addResources("twitch", "ad.audio.audioAdsPatch") addResources("twitch", "ad.audio.audioAdsPatch")

View File

@@ -19,7 +19,7 @@ val embeddedAdsPatch = bytecodePatch(
settingsPatch, settingsPatch,
) )
compatibleWith("tv.twitch.android.app") compatibleWith("tv.twitch.android.app"("16.9.1", "25.3.0"))
execute { execute {
addResources("twitch", "ad.embedded.embeddedAdsPatch") addResources("twitch", "ad.embedded.embeddedAdsPatch")

View File

@@ -155,7 +155,5 @@ val videoAdsPatch = bytecodePatch(
}, },
) )
compatibleWith( compatibleWith("tv.twitch.android.app"("16.9.1", "25.3.0"))
"tv.twitch.android.app",
)
} }

View File

@@ -22,7 +22,7 @@ val showDeletedMessagesPatch = bytecodePatch(
addResourcesPatch, addResourcesPatch,
) )
compatibleWith("tv.twitch.android.app") compatibleWith("tv.twitch.android.app"("16.9.1", "25.3.0"))
fun createSpoilerConditionInstructions(register: String = "v0") = """ fun createSpoilerConditionInstructions(register: String = "v0") = """
invoke-static {}, Lapp/revanced/extension/twitch/patches/ShowDeletedMessagesPatch;->shouldUseSpoiler()Z invoke-static {}, Lapp/revanced/extension/twitch/patches/ShowDeletedMessagesPatch;->shouldUseSpoiler()Z

View File

@@ -20,7 +20,7 @@ val autoClaimChannelPointsPatch = bytecodePatch(
addResourcesPatch, addResourcesPatch,
) )
compatibleWith("tv.twitch.android.app") compatibleWith("tv.twitch.android.app"("16.9.1", "25.3.0"))
execute { execute {
addResources("twitch", "chat.autoclaim.autoClaimChannelPointsPatch") addResources("twitch", "chat.autoclaim.autoClaimChannelPointsPatch")

View File

@@ -20,7 +20,7 @@ val debugModePatch = bytecodePatch(
addResourcesPatch, addResourcesPatch,
) )
compatibleWith("tv.twitch.android.app") compatibleWith("tv.twitch.android.app"("16.9.1", "25.3.0"))
execute { execute {
addResources("twitch", "debug.debugModePatch") addResources("twitch", "debug.debugModePatch")

View File

@@ -48,7 +48,7 @@ val settingsPatch = bytecodePatch(
settingsPatch(preferences = preferences), settingsPatch(preferences = preferences),
) )
compatibleWith("tv.twitch.android.app") compatibleWith("tv.twitch.android.app"("16.9.1"))
execute { execute {
addResources("twitch", "misc.settings.settingsPatch") addResources("twitch", "misc.settings.settingsPatch")

View File

@@ -57,6 +57,7 @@ val hidePlayerFlyoutMenuPatch = bytecodePatch(
), ),
SwitchPreference("revanced_hide_player_flyout_watch_in_vr"), SwitchPreference("revanced_hide_player_flyout_watch_in_vr"),
SwitchPreference("revanced_hide_player_flyout_sleep_timer"), SwitchPreference("revanced_hide_player_flyout_sleep_timer"),
SwitchPreference("revanced_hide_player_flyout_video_quality"),
SwitchPreference("revanced_hide_player_flyout_video_quality_footer"), SwitchPreference("revanced_hide_player_flyout_video_quality_footer"),
), ),
), ),

View File

@@ -282,7 +282,7 @@ val playerControlsPatch = bytecodePatch(
// The change to support this is simple and only requires adding buttons to both layout files, // The change to support this is simple and only requires adding buttons to both layout files,
// but for now force this different layout off since it's still an experimental test. // but for now force this different layout off since it's still an experimental test.
if (is_19_35_or_greater) { if (is_19_35_or_greater) {
playerBottomControlsExploderFeatureFlagFingerprint.method.returnEarly() playerBottomControlsExploderFeatureFlagFingerprint.method.returnLate(false)
} }
// A/B test of new top overlay controls. Two different layouts can be used: // A/B test of new top overlay controls. Two different layouts can be used:

View File

@@ -1,23 +1,27 @@
package app.revanced.patches.youtube.video.audio package app.revanced.patches.youtube.video.audio
import app.revanced.patcher.fingerprint import app.revanced.patcher.fingerprint
import app.revanced.util.containsLiteralInstruction
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
internal val streamingModelBuilderFingerprint = fingerprint { internal val formatStreamModelToStringFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("L") returns("Ljava/lang/String;")
strings("vprng") custom { method, classDef ->
method.name == "toString" && classDef.type ==
"Lcom/google/android/libraries/youtube/innertube/model/media/FormatStreamModel;"
}
} }
internal val menuItemAudioTrackFingerprint = fingerprint { internal const val AUDIO_STREAM_IGNORE_DEFAULT_FEATURE_FLAG = 45666189L
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
parameters("L") internal val selectAudioStreamFingerprint = fingerprint {
returns("V") accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
strings("menu_item_audio_track") returns("L")
custom { method, _ ->
method.parameters.size > 2 // Method has a large number of parameters and may change.
&& method.parameters[1].type == "Lcom/google/android/libraries/youtube/innertube/model/media/PlayerConfigModel;"
&& method.containsLiteralInstruction(AUDIO_STREAM_IGNORE_DEFAULT_FEATURE_FLAG)
}
} }
internal val audioStreamingTypeSelector = fingerprint {
accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL)
returns("L")
strings("raw") // String is not unique
}

View File

@@ -5,22 +5,22 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.playservice.is_20_07_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.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.util.getReference import app.revanced.util.findMethodFromToString
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.insertLiteralOverride
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.immutable.ImmutableField import com.android.tools.smali.dexlib2.immutable.ImmutableField
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
@@ -37,6 +37,7 @@ val forceOriginalAudioPatch = bytecodePatch(
sharedExtensionPatch, sharedExtensionPatch,
settingsPatch, settingsPatch,
addResourcesPatch, addResourcesPatch,
versionCheckPatch
) )
compatibleWith( compatibleWith(
@@ -60,100 +61,93 @@ val forceOriginalAudioPatch = bytecodePatch(
) )
) )
fun Method.firstFormatStreamingModelCall( // Disable feature flag that ignores the default track flag
returnType: String = "Ljava/lang/String;" // and instead overrides to the user region language.
): MutableMethod { if (is_20_07_or_greater) {
val audioTrackIdIndex = indexOfFirstInstructionOrThrow { selectAudioStreamFingerprint.method.insertLiteralOverride(
val reference = getReference<MethodReference>() AUDIO_STREAM_IGNORE_DEFAULT_FEATURE_FLAG,
reference?.definingClass == "Lcom/google/android/libraries/youtube/innertube/model/media/FormatStreamModel;" "$EXTENSION_CLASS_DESCRIPTOR->ignoreDefaultAudioStream(Z)Z"
&& reference.returnType == returnType )
}
return navigate(this).to(audioTrackIdIndex).stop()
} }
// Accessor methods of FormatStreamModel have no string constants and formatStreamModelToStringFingerprint.let {
// opcodes are identical to other methods in the same class, val isDefaultAudioTrackMethod = it.originalMethod.findMethodFromToString("isDefaultAudioTrack=")
// so must walk from another class that use the methods. val audioTrackDisplayNameMethod = it.originalMethod.findMethodFromToString("audioTrackDisplayName=")
val isDefaultMethod = streamingModelBuilderFingerprint.originalMethod.firstFormatStreamingModelCall("Z") val audioTrackIdMethod = it.originalMethod.findMethodFromToString("audioTrackId=")
val audioTrackIdMethod = menuItemAudioTrackFingerprint.originalMethod.firstFormatStreamingModelCall()
val audioTrackDisplayNameMethod = audioStreamingTypeSelector.originalMethod.firstFormatStreamingModelCall()
val formatStreamModelClass = proxy(classes.first {
it.type == audioTrackIdMethod.definingClass
}).mutableClass
formatStreamModelClass.apply { it.classDef.apply {
// Add a new field to store the override. // Add a new field to store the override.
val helperFieldName = "isDefaultAudioTrackOverride" val helperFieldName = "patch_isDefaultAudioTrackOverride"
fields.add( fields.add(
ImmutableField( ImmutableField(
type, type,
helperFieldName, helperFieldName,
"Ljava/lang/Boolean;", "Ljava/lang/Boolean;",
// Boolean is a 100% immutable class (all fields are final) // Boolean is a 100% immutable class (all fields are final)
// and safe to write to a shared field without volatile/synchronization, // and safe to write to a shared field without volatile/synchronization,
// but without volatile the field can show stale data // but without volatile the field can show stale data
// and the same field is calculated more than once by different threads. // and the same field is calculated more than once by different threads.
AccessFlags.PRIVATE.value or AccessFlags.VOLATILE.value, AccessFlags.PRIVATE.value or AccessFlags.VOLATILE.value,
null,
null,
null
).toMutable()
)
// Add a helper method because the isDefaultAudioTrack() has only 2 registers and 3 are needed.
val helperMethodClass = type
val helperMethodName = "patch_isDefaultAudioTrack"
val helperMethod = ImmutableMethod(
helperMethodClass,
helperMethodName,
listOf(ImmutableMethodParameter("Z", null, null)),
"Z",
AccessFlags.PRIVATE.value,
null, null,
null, null,
null MutableMethodImplementation(6),
).toMutable() ).toMutable().apply {
) addInstructionsWithLabels(
0,
"""
iget-object v0, p0, $helperMethodClass->$helperFieldName:Ljava/lang/Boolean;
if-eqz v0, :call_extension
invoke-virtual { v0 }, Ljava/lang/Boolean;->booleanValue()Z
move-result v3
return v3
// Add a helper method because the isDefaultAudioTrack() has only 2 registers and 3 are needed. :call_extension
val helperMethodClass = type invoke-virtual { p0 }, $audioTrackIdMethod
val helperMethodName = "extension_isDefaultAudioTrack" move-result-object v1
val helperMethod = ImmutableMethod(
helperMethodClass,
helperMethodName,
listOf(ImmutableMethodParameter("Z", null, null)),
"Z",
AccessFlags.PRIVATE.value,
null,
null,
MutableMethodImplementation(6),
).toMutable().apply {
addInstructionsWithLabels(
0,
"""
iget-object v0, p0, $helperMethodClass->$helperFieldName:Ljava/lang/Boolean;
if-eqz v0, :call_extension
invoke-virtual { v0 }, Ljava/lang/Boolean;->booleanValue()Z
move-result v3
return v3
:call_extension invoke-virtual { p0 }, $audioTrackDisplayNameMethod
invoke-virtual { p0 }, $audioTrackIdMethod move-result-object v2
move-result-object v1
invoke-virtual { p0 }, $audioTrackDisplayNameMethod invoke-static { p1, v1, v2 }, $EXTENSION_CLASS_DESCRIPTOR->isDefaultAudioStream(ZLjava/lang/String;Ljava/lang/String;)Z
move-result-object v2 move-result v3
invoke-static { p1, v1, v2 }, $EXTENSION_CLASS_DESCRIPTOR->isDefaultAudioStream(ZLjava/lang/String;Ljava/lang/String;)Z invoke-static { v3 }, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;
move-result v3 move-result-object v0
iput-object v0, p0, $helperMethodClass->$helperFieldName:Ljava/lang/Boolean;
return v3
"""
)
}
methods.add(helperMethod)
invoke-static { v3 }, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean; // Modify isDefaultAudioTrack() to call extension helper method.
move-result-object v0 isDefaultAudioTrackMethod.apply {
iput-object v0, p0, $helperMethodClass->$helperFieldName:Ljava/lang/Boolean; val index = indexOfFirstInstructionOrThrow(Opcode.RETURN)
return v3 val register = getInstruction<OneRegisterInstruction>(index).registerA
"""
)
}
methods.add(helperMethod)
// Modify isDefaultAudioTrack() to call extension helper method. addInstructions(
isDefaultMethod.apply { index,
val index = indexOfFirstInstructionOrThrow(Opcode.RETURN) """
val register = getInstruction<OneRegisterInstruction>(index).registerA invoke-direct { p0, v$register }, $helperMethodClass->$helperMethodName(Z)Z
move-result v$register
addInstructions( """
index, )
""" }
invoke-direct { p0, v$register }, $helperMethodClass->$helperMethodName(Z)Z
move-result v$register
"""
)
} }
} }
} }

View File

@@ -63,7 +63,7 @@ val disableHdrPatch = bytecodePatch(
return v0 return v0
:useHdr :useHdr
nop nop
""" """
) )
} }
} }

View File

@@ -133,3 +133,46 @@ internal val playbackSpeedClassFingerprint = fingerprint {
) )
strings("PLAYBACK_RATE_MENU_BOTTOM_SHEET_FRAGMENT") strings("PLAYBACK_RATE_MENU_BOTTOM_SHEET_FRAGMENT")
} }
internal const val YOUTUBE_VIDEO_QUALITY_CLASS_TYPE = "Lcom/google/android/libraries/youtube/innertube/model/media/VideoQuality;"
internal val videoQualityFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
parameters(
"I", // Resolution.
"Ljava/lang/String;", // Human readable resolution: "480p", "1080p Premium", etc
"Z",
"L"
)
custom { _, classDef ->
classDef.type == YOUTUBE_VIDEO_QUALITY_CLASS_TYPE
}
}
internal val videoQualitySetterFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("V")
parameters("[L", "I", "Z")
opcodes(
Opcode.IF_EQZ,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.IPUT_BOOLEAN,
)
strings("menu_item_video_quality")
}
/**
* Matches with the class found in [videoQualitySetterFingerprint].
*/
internal val setVideoQualityFingerprint = fingerprint {
returns("V")
parameters("L")
opcodes(
Opcode.IGET_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IGET_OBJECT,
)
}

View File

@@ -38,7 +38,9 @@ import com.android.tools.smali.dexlib2.util.MethodUtil
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/VideoInformation;" private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/VideoInformation;"
private const val EXTENSION_PLAYER_INTERFACE = private const val EXTENSION_PLAYER_INTERFACE =
"Lapp/revanced/extension/youtube/patches/VideoInformation${'$'}PlaybackController;" "Lapp/revanced/extension/youtube/patches/VideoInformation\$PlaybackController;"
private const val EXTENSION_VIDEO_QUALITY_MENU_INTERFACE =
"Lapp/revanced/extension/youtube/patches/VideoInformation\$VideoQualityMenuInterface;"
private lateinit var playerInitMethod: MutableMethod private lateinit var playerInitMethod: MutableMethod
private var playerInitInsertIndex = -1 private var playerInitInsertIndex = -1
@@ -83,7 +85,6 @@ val videoInformationPatch = bytecodePatch(
) )
execute { execute {
playerInitMethod = playerInitFingerprint.classDef.methods.first { MethodUtil.isConstructor(it) } playerInitMethod = playerInitFingerprint.classDef.methods.first { MethodUtil.isConstructor(it) }
// Find the location of the first invoke-direct call and extract the register storing the 'this' object reference. // Find the location of the first invoke-direct call and extract the register storing the 'this' object reference.
@@ -93,9 +94,6 @@ val videoInformationPatch = bytecodePatch(
playerInitInsertRegister = playerInitMethod.getInstruction<FiveRegisterInstruction>(initThisIndex).registerC playerInitInsertRegister = playerInitMethod.getInstruction<FiveRegisterInstruction>(initThisIndex).registerC
playerInitInsertIndex = initThisIndex + 1 playerInitInsertIndex = initThisIndex + 1
// Hook the player controller for use through the extension.
onCreateHook(EXTENSION_CLASS_DESCRIPTOR, "initialize")
val seekFingerprintResultMethod = seekFingerprint.match(playerInitFingerprint.originalClassDef).method val seekFingerprintResultMethod = seekFingerprint.match(playerInitFingerprint.originalClassDef).method
val seekRelativeFingerprintResultMethod = val seekRelativeFingerprintResultMethod =
seekRelativeFingerprint.match(playerInitFingerprint.originalClassDef).method seekRelativeFingerprint.match(playerInitFingerprint.originalClassDef).method
@@ -272,6 +270,131 @@ val videoInformationPatch = bytecodePatch(
speedSelectionValueRegister = getInstruction<TwoRegisterInstruction>(index).registerA speedSelectionValueRegister = getInstruction<TwoRegisterInstruction>(index).registerA
} }
videoQualityFingerprint.let {
// Fix bad data used by YouTube.
it.method.addInstructions(
0,
"""
invoke-static { p2, p1 }, $EXTENSION_CLASS_DESCRIPTOR->fixVideoQualityResolution(Ljava/lang/String;I)I
move-result p1
"""
)
// Add methods to access obfuscated quality fields.
it.classDef.apply {
methods.add(
ImmutableMethod(
type,
"patch_getQualityName",
listOf(),
"Ljava/lang/String;",
AccessFlags.PUBLIC.value or AccessFlags.FINAL.value,
null,
null,
MutableMethodImplementation(2),
).toMutable().apply {
// Only one string field.
val qualityNameField = fields.single { field ->
field.type == "Ljava/lang/String;"
}
addInstructions(
0,
"""
iget-object v0, p0, $qualityNameField
return-object v0
"""
)
}
)
methods.add(
ImmutableMethod(
type,
"patch_getResolution",
listOf(),
"I",
AccessFlags.PUBLIC.value or AccessFlags.FINAL.value,
null,
null,
MutableMethodImplementation(2),
).toMutable().apply {
val resolutionField = fields.single { field ->
field.type == "I"
}
addInstructions(
0,
"""
iget v0, p0, $resolutionField
return v0
"""
)
}
)
}
}
// Detect video quality changes and override the current quality.
setVideoQualityFingerprint.match(
videoQualitySetterFingerprint.originalClassDef
).let { match ->
// This instruction refers to the field with the type that contains the setQuality method.
val onItemClickListenerClassReference = match.method
.getInstruction<ReferenceInstruction>(0).reference
val setQualityFieldReference = match.method
.getInstruction<ReferenceInstruction>(1).reference as FieldReference
proxy(
classes.find { classDef ->
classDef.type == setQualityFieldReference.type
}!!
).mutableClass.apply {
// Add interface and helper methods to allow extension code to call obfuscated methods.
interfaces.add(EXTENSION_VIDEO_QUALITY_MENU_INTERFACE)
methods.add(
ImmutableMethod(
type,
"patch_setQuality",
listOf(
ImmutableMethodParameter(YOUTUBE_VIDEO_QUALITY_CLASS_TYPE, null, null)
),
"V",
AccessFlags.PUBLIC.value or AccessFlags.FINAL.value,
null,
null,
MutableMethodImplementation(2),
).toMutable().apply {
val setQualityMenuIndexMethod = methods.single { method ->
method.parameterTypes.firstOrNull() == YOUTUBE_VIDEO_QUALITY_CLASS_TYPE
}
addInstructions(
0,
"""
invoke-virtual { p0, p1 }, $setQualityMenuIndexMethod
return-void
"""
)
}
)
}
videoQualitySetterFingerprint.method.addInstructions(
0,
"""
# Get object instance to invoke setQuality method.
iget-object v0, p0, $onItemClickListenerClassReference
iget-object v0, v0, $setQualityFieldReference
invoke-static { p1, v0, p2 }, $EXTENSION_CLASS_DESCRIPTOR->setVideoQuality([$YOUTUBE_VIDEO_QUALITY_CLASS_TYPE${EXTENSION_VIDEO_QUALITY_MENU_INTERFACE}I)I
move-result p2
"""
)
}
onCreateHook(EXTENSION_CLASS_DESCRIPTOR, "initialize")
videoSpeedChangedHook(EXTENSION_CLASS_DESCRIPTOR, "videoSpeedChanged") videoSpeedChangedHook(EXTENSION_CLASS_DESCRIPTOR, "videoSpeedChanged")
userSelectedPlaybackSpeedHook(EXTENSION_CLASS_DESCRIPTOR, "userSelectedPlaybackSpeed") userSelectedPlaybackSpeedHook(EXTENSION_CLASS_DESCRIPTOR, "userSelectedPlaybackSpeed")
} }
@@ -282,8 +405,8 @@ private fun addSeekInterfaceMethods(targetClass: MutableClass, seekToMethod: Met
targetClass.interfaces.add(EXTENSION_PLAYER_INTERFACE) targetClass.interfaces.add(EXTENSION_PLAYER_INTERFACE)
arrayOf( arrayOf(
Triple(seekToMethod, "seekTo", true), Triple(seekToMethod, "patch_seekTo", true),
Triple(seekToRelativeMethod, "seekToRelative", false), Triple(seekToRelativeMethod, "patch_seekToRelative", false),
).forEach { (method, name, returnsBoolean) -> ).forEach { (method, name, returnsBoolean) ->
// Add interface method. // Add interface method.
// Get enum type for the seek helper method. // Get enum type for the seek helper method.

View File

@@ -5,34 +5,6 @@ import app.revanced.util.literal
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
internal const val YOUTUBE_VIDEO_QUALITY_CLASS_TYPE = "Lcom/google/android/libraries/youtube/innertube/model/media/VideoQuality;"
internal val videoQualityFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
parameters(
"I", // Resolution.
"Ljava/lang/String;", // Human readable resolution: "480p", "1080p Premium", etc
"Z",
"L"
)
custom { _, classDef ->
classDef.type == YOUTUBE_VIDEO_QUALITY_CLASS_TYPE
}
}
/**
* Matches with the class found in [videoQualitySetterFingerprint].
*/
internal val setVideoQualityFingerprint = fingerprint {
returns("V")
parameters("L")
opcodes(
Opcode.IGET_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IGET_OBJECT,
)
}
internal val videoQualityItemOnClickParentFingerprint = fingerprint { internal val videoQualityItemOnClickParentFingerprint = fingerprint {
returns("V") returns("V")
strings("VIDEO_QUALITIES_MENU_BOTTOM_SHEET_FRAGMENT") strings("VIDEO_QUALITIES_MENU_BOTTOM_SHEET_FRAGMENT")
@@ -54,19 +26,6 @@ internal val videoQualityItemOnClickFingerprint = fingerprint {
} }
} }
internal val videoQualitySetterFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("V")
parameters("[L", "I", "Z")
opcodes(
Opcode.IF_EQZ,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.IPUT_BOOLEAN,
)
strings("menu_item_video_quality")
}
internal val videoQualityMenuOptionsFingerprint = fingerprint { internal val videoQualityMenuOptionsFingerprint = fingerprint {
accessFlags(AccessFlags.STATIC) accessFlags(AccessFlags.STATIC)

View File

@@ -1,10 +1,8 @@
package app.revanced.patches.youtube.video.quality package app.revanced.patches.youtube.video.quality
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.ListPreference import app.revanced.patches.shared.misc.settings.preference.ListPreference
@@ -15,18 +13,10 @@ import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.shared.videoQualityChangedFingerprint import app.revanced.patches.youtube.shared.videoQualityChangedFingerprint
import app.revanced.patches.youtube.video.information.onCreateHook import app.revanced.patches.youtube.video.information.onCreateHook
import app.revanced.patches.youtube.video.information.videoInformationPatch import app.revanced.patches.youtube.video.information.videoInformationPatch
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
private const val EXTENSION_CLASS_DESCRIPTOR = private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch;" "Lapp/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch;"
private const val EXTENSION_VIDEO_QUALITY_MENU_INTERFACE =
"Lapp/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch\$VideoQualityMenuInterface;"
val rememberVideoQualityPatch = bytecodePatch { val rememberVideoQualityPatch = bytecodePatch {
dependsOn( dependsOn(
@@ -69,131 +59,6 @@ val rememberVideoQualityPatch = bytecodePatch {
onCreateHook(EXTENSION_CLASS_DESCRIPTOR, "newVideoStarted") onCreateHook(EXTENSION_CLASS_DESCRIPTOR, "newVideoStarted")
videoQualityFingerprint.let {
// Fix bad data used by YouTube.
it.method.addInstructions(
0,
"""
invoke-static { p2, p1 }, $EXTENSION_CLASS_DESCRIPTOR->fixVideoQualityResolution(Ljava/lang/String;I)I
move-result p1
"""
)
// Add methods to access obfuscated quality fields.
it.classDef.apply {
methods.add(
ImmutableMethod(
type,
"patch_getQualityName",
listOf(),
"Ljava/lang/String;",
AccessFlags.PUBLIC.value or AccessFlags.FINAL.value,
null,
null,
MutableMethodImplementation(2),
).toMutable().apply {
// Only one string field.
val qualityNameField = fields.single { field ->
field.type == "Ljava/lang/String;"
}
addInstructions(
0,
"""
iget-object v0, p0, $qualityNameField
return-object v0
"""
)
}
)
methods.add(
ImmutableMethod(
type,
"patch_getResolution",
listOf(),
"I",
AccessFlags.PUBLIC.value or AccessFlags.FINAL.value,
null,
null,
MutableMethodImplementation(2),
).toMutable().apply {
val resolutionField = fields.single { field ->
field.type == "I"
}
addInstructions(
0,
"""
iget v0, p0, $resolutionField
return v0
"""
)
}
)
}
}
// Inject a call to set the remembered quality once a video loads.
setVideoQualityFingerprint.match(
videoQualitySetterFingerprint.originalClassDef
).let { match ->
// This instruction refers to the field with the type that contains the setQuality method.
val instructions = match.method.implementation!!.instructions
val onItemClickListenerClassReference =
(instructions.elementAt(0) as ReferenceInstruction).reference
val setQualityFieldReference =
((instructions.elementAt(1) as ReferenceInstruction).reference) as FieldReference
proxy(
classes.find { classDef ->
classDef.type == setQualityFieldReference.type
}!!
).mutableClass.apply {
// Add interface and helper methods to allow extension code to call obfuscated methods.
interfaces.add(EXTENSION_VIDEO_QUALITY_MENU_INTERFACE)
methods.add(
ImmutableMethod(
type,
"patch_setQuality",
listOf(
ImmutableMethodParameter(YOUTUBE_VIDEO_QUALITY_CLASS_TYPE, null, null)
),
"V",
AccessFlags.PUBLIC.value or AccessFlags.FINAL.value,
null,
null,
MutableMethodImplementation(2),
).toMutable().apply {
val setQualityMenuIndexMethod = methods.single { method ->
method.parameterTypes.firstOrNull() == YOUTUBE_VIDEO_QUALITY_CLASS_TYPE
}
addInstructions(
0,
"""
invoke-virtual { p0, p1 }, $setQualityMenuIndexMethod
return-void
"""
)
}
)
}
videoQualitySetterFingerprint.method.addInstructions(
0,
"""
# Get object instance to invoke setQuality method.
iget-object v0, p0, $onItemClickListenerClassReference
iget-object v0, v0, $setQualityFieldReference
invoke-static { p1, v0, p2 }, $EXTENSION_CLASS_DESCRIPTOR->setVideoQuality([$YOUTUBE_VIDEO_QUALITY_CLASS_TYPE${EXTENSION_VIDEO_QUALITY_MENU_INTERFACE}I)I
move-result p2
"""
)
}
// Inject a call to remember the selected quality for Shorts. // Inject a call to remember the selected quality for Shorts.
videoQualityItemOnClickFingerprint.match( videoQualityItemOnClickFingerprint.match(
videoQualityItemOnClickParentFingerprint.classDef videoQualityItemOnClickParentFingerprint.classDef

View File

@@ -1,4 +1,4 @@
package app.revanced.patches.youtube.video.quality.button package app.revanced.patches.youtube.video.quality
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.patch.resourcePatch
@@ -9,7 +9,6 @@ import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.playercontrols.* import app.revanced.patches.youtube.misc.playercontrols.*
import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.video.quality.rememberVideoQualityPatch
import app.revanced.util.ResourceGroup import app.revanced.util.ResourceGroup
import app.revanced.util.copyResources import app.revanced.util.copyResources
@@ -21,14 +20,7 @@ private val videoQualityButtonResourcePatch = resourcePatch {
"qualitybutton", "qualitybutton",
ResourceGroup( ResourceGroup(
"drawable", "drawable",
"revanced_video_quality_dialog_button_ld.xml", "revanced_video_quality_dialog_button_rectangle.xml",
"revanced_video_quality_dialog_button_sd.xml",
"revanced_video_quality_dialog_button_hd.xml",
"revanced_video_quality_dialog_button_fhd.xml",
"revanced_video_quality_dialog_button_fhd_plus.xml",
"revanced_video_quality_dialog_button_qhd.xml",
"revanced_video_quality_dialog_button_4k.xml",
"revanced_video_quality_dialog_button_unknown.xml",
), ),
) )
@@ -39,7 +31,7 @@ private val videoQualityButtonResourcePatch = resourcePatch {
private const val QUALITY_BUTTON_CLASS_DESCRIPTOR = private const val QUALITY_BUTTON_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/videoplayer/VideoQualityDialogButton;" "Lapp/revanced/extension/youtube/videoplayer/VideoQualityDialogButton;"
val videoQualityButtonPatch = bytecodePatch( val videoQualityDialogButtonPatch = bytecodePatch(
description = "Adds the option to display video quality dialog button in the video player.", description = "Adds the option to display video quality dialog button in the video player.",
) { ) {
dependsOn( dependsOn(
@@ -52,7 +44,7 @@ val videoQualityButtonPatch = bytecodePatch(
) )
execute { execute {
addResources("youtube", "video.quality.button.videoQualityButtonPatch") addResources("youtube", "video.quality.button.videoQualityDialogButtonPatch")
PreferenceScreen.PLAYER.addPreferences( PreferenceScreen.PLAYER.addPreferences(
SwitchPreference("revanced_video_quality_dialog_button"), SwitchPreference("revanced_video_quality_dialog_button"),

View File

@@ -5,7 +5,6 @@ import app.revanced.patches.shared.misc.settings.preference.BasePreference
import app.revanced.patches.shared.misc.settings.preference.PreferenceCategory import app.revanced.patches.shared.misc.settings.preference.PreferenceCategory
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.video.quality.button.videoQualityButtonPatch
/** /**
* Video quality settings. Used to organize all speed related settings together. * Video quality settings. Used to organize all speed related settings together.
@@ -20,7 +19,7 @@ val videoQualityPatch = bytecodePatch(
dependsOn( dependsOn(
rememberVideoQualityPatch, rememberVideoQualityPatch,
advancedVideoQualityMenuPatch, advancedVideoQualityMenuPatch,
videoQualityButtonPatch, videoQualityDialogButtonPatch,
) )
compatibleWith( compatibleWith(

View File

@@ -9,6 +9,9 @@ import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.playercontrols.* import app.revanced.patches.youtube.misc.playercontrols.*
import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.video.information.userSelectedPlaybackSpeedHook
import app.revanced.patches.youtube.video.information.videoInformationPatch
import app.revanced.patches.youtube.video.information.videoSpeedChangedHook
import app.revanced.patches.youtube.video.speed.custom.customPlaybackSpeedPatch import app.revanced.patches.youtube.video.speed.custom.customPlaybackSpeedPatch
import app.revanced.util.ResourceGroup import app.revanced.util.ResourceGroup
import app.revanced.util.copyResources import app.revanced.util.copyResources
@@ -21,8 +24,8 @@ private val playbackSpeedButtonResourcePatch = resourcePatch {
"speedbutton", "speedbutton",
ResourceGroup( ResourceGroup(
"drawable", "drawable",
"revanced_playback_speed_dialog_button.xml", "revanced_playback_speed_dialog_button_rectangle.xml"
), )
) )
addBottomControl("speedbutton") addBottomControl("speedbutton")
@@ -42,6 +45,7 @@ val playbackSpeedButtonPatch = bytecodePatch(
customPlaybackSpeedPatch, customPlaybackSpeedPatch,
playbackSpeedButtonResourcePatch, playbackSpeedButtonResourcePatch,
playerControlsPatch, playerControlsPatch,
videoInformationPatch,
) )
execute { execute {
@@ -53,5 +57,8 @@ val playbackSpeedButtonPatch = bytecodePatch(
initializeBottomControl(SPEED_BUTTON_CLASS_DESCRIPTOR) initializeBottomControl(SPEED_BUTTON_CLASS_DESCRIPTOR)
injectVisibilityCheckCall(SPEED_BUTTON_CLASS_DESCRIPTOR) injectVisibilityCheckCall(SPEED_BUTTON_CLASS_DESCRIPTOR)
videoSpeedChangedHook(SPEED_BUTTON_CLASS_DESCRIPTOR, "videoSpeedChanged")
userSelectedPlaybackSpeedHook(SPEED_BUTTON_CLASS_DESCRIPTOR, "videoSpeedChanged")
} }
} }

View File

@@ -32,7 +32,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.RegisterRangeInstructio
import com.android.tools.smali.dexlib2.iface.instruction.ThreeRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ThreeRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.Reference import com.android.tools.smali.dexlib2.iface.reference.Reference
import com.android.tools.smali.dexlib2.iface.reference.StringReference
import com.android.tools.smali.dexlib2.immutable.ImmutableField import com.android.tools.smali.dexlib2.immutable.ImmutableField
import com.android.tools.smali.dexlib2.util.MethodUtil import com.android.tools.smali.dexlib2.util.MethodUtil
import java.util.EnumSet import java.util.EnumSet
@@ -171,6 +174,79 @@ internal val Instruction.isBranchInstruction: Boolean
internal val Instruction.isReturnInstruction: Boolean internal val Instruction.isReturnInstruction: Boolean
get() = this.opcode in returnOpcodes get() = this.opcode in returnOpcodes
/**
* Find the instruction index used for a toString() StringBuilder write of a given String name.
*
* @param fieldName The name of the field to find. Partial matches are allowed.
*/
private fun Method.findInstructionIndexFromToString(fieldName: String) : Int {
val stringIndex = indexOfFirstInstruction {
val reference = getReference<StringReference>()
reference?.string?.contains(fieldName) == true
}
if (stringIndex < 0) {
throw IllegalArgumentException("Could not find usage of string: '$fieldName'")
}
val stringRegister = getInstruction<OneRegisterInstruction>(stringIndex).registerA
// Find use of the string with a StringBuilder.
val stringUsageIndex = indexOfFirstInstruction(stringIndex) {
val reference = getReference<MethodReference>()
reference?.definingClass == "Ljava/lang/StringBuilder;" &&
(this as? FiveRegisterInstruction)?.registerD == stringRegister
}
if (stringUsageIndex < 0) {
throw IllegalArgumentException("Could not find StringBuilder usage in: $this")
}
// Find the next usage of StringBuilder, which should be the desired field.
val fieldUsageIndex = indexOfFirstInstruction(stringUsageIndex + 1) {
val reference = getReference<MethodReference>()
reference?.definingClass == "Ljava/lang/StringBuilder;" && reference.name == "append"
}
if (fieldUsageIndex < 0) {
// Should never happen.
throw IllegalArgumentException("Could not find StringBuilder append usage in: $this")
}
val fieldUsageRegister = getInstruction<FiveRegisterInstruction>(fieldUsageIndex).registerD
// Look backwards up the method to find the instruction that sets the register.
var fieldSetIndex = indexOfFirstInstructionReversedOrThrow(fieldUsageIndex - 1) {
fieldUsageRegister == writeRegister
}
// If the field is a method call, then adjust from MOVE_RESULT to the method call.
val fieldSetOpcode = getInstruction(fieldSetIndex).opcode
if (fieldSetOpcode == MOVE_RESULT ||
fieldSetOpcode == MOVE_RESULT_WIDE ||
fieldSetOpcode == MOVE_RESULT_OBJECT) {
fieldSetIndex--
}
return fieldSetIndex
}
/**
* Find the method used for a toString() StringBuilder write of a given String name.
*
* @param fieldName The name of the field to find. Partial matches are allowed.
*/
context(BytecodePatchContext)
internal fun Method.findMethodFromToString(fieldName: String) : MutableMethod {
val methodUsageIndex = findInstructionIndexFromToString(fieldName)
return navigate(this).to(methodUsageIndex).stop()
}
/**
* Find the field used for a toString() StringBuilder write of a given String name.
*
* @param fieldName The name of the field to find. Partial matches are allowed.
*/
internal fun Method.findFieldFromToString(fieldName: String) : FieldReference {
val methodUsageIndex = findInstructionIndexFromToString(fieldName)
return getInstruction<ReferenceInstruction>(methodUsageIndex).getReference<FieldReference>()!!
}
/** /**
* Adds public [AccessFlags] and removes private and protected flags (if present). * Adds public [AccessFlags] and removes private and protected flags (if present).
*/ */
@@ -594,7 +670,7 @@ fun Method.indexOfFirstInstructionReversed(targetOpcode: Opcode): Int = indexOfF
/** /**
* Get the index of matching instruction, * Get the index of matching instruction,
* starting from and [startIndex] and searching down. * starting from [startIndex] and searching down.
* *
* @param startIndex Optional starting index to search down from. Searching includes the start index. * @param startIndex Optional starting index to search down from. Searching includes the start index.
* @return The index of the instruction. * @return The index of the instruction.
@@ -617,7 +693,7 @@ fun Method.indexOfFirstInstructionReversedOrThrow(targetOpcode: Opcode): Int = i
/** /**
* Get the index of matching instruction, * Get the index of matching instruction,
* starting from and [startIndex] and searching down. * starting from [startIndex] and searching down.
* *
* @param startIndex Optional starting index to search down from. Searching includes the start index. * @param startIndex Optional starting index to search down from. Searching includes the start index.
* @return The index of the instruction. * @return The index of the instruction.

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -693,6 +693,9 @@ Second \"item\" text"</string>
<string name="revanced_hide_player_flyout_watch_in_vr_title">إخفاء المشاهدة في VR</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">إخفاء المشاهدة في VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">تم إخفاء قائمة المشاهدة في الوضع الافتراضي</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">تم إخفاء قائمة المشاهدة في الوضع الافتراضي</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">يتم عرض قائمة المشاهدة في الوضع الافتراضي</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">يتم عرض قائمة المشاهدة في الوضع الافتراضي</string>
<string name="revanced_hide_player_flyout_video_quality_title">إخفاء قائمة جودة الفيديو</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">قائمة جودة الفيديو مخفية</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">قائمة جودة الفيديو معروضة</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">إخفاء تذييل قائمة جودة الفيديو</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">إخفاء تذييل قائمة جودة الفيديو</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">تم إخفاء تذييل قائمة جودة الفيديو</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">تم إخفاء تذييل قائمة جودة الفيديو</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">يتم عرض تذييل قائمة جودة الفيديو</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">يتم عرض تذييل قائمة جودة الفيديو</string>
@@ -1465,7 +1468,7 @@ Second \"item\" text"</string>
<string name="revanced_playback_speed_dialog_button_summary_on">الزر معروض. انقر مع الاستمرار لإعادة ضبط سرعة التشغيل إلى الوضع الافتراضي</string> <string name="revanced_playback_speed_dialog_button_summary_on">الزر معروض. انقر مع الاستمرار لإعادة ضبط سرعة التشغيل إلى الوضع الافتراضي</string>
<string name="revanced_playback_speed_dialog_button_summary_off">لا يتم عرض الزر</string> <string name="revanced_playback_speed_dialog_button_summary_off">لا يتم عرض الزر</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">عرض زر جودة الفيديو</string> <string name="revanced_video_quality_dialog_button_title">عرض زر جودة الفيديو</string>
<string name="revanced_video_quality_dialog_button_summary_on">الزر معروض. انقر مع الاستمرار لإعادة تعيين الجودة إلى الافتراضي</string> <string name="revanced_video_quality_dialog_button_summary_on">الزر معروض. انقر مع الاستمرار لإعادة تعيين الجودة إلى الافتراضي</string>
<string name="revanced_video_quality_dialog_button_summary_off">الزر غير معروض</string> <string name="revanced_video_quality_dialog_button_summary_off">الزر غير معروض</string>

View File

@@ -224,7 +224,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -693,6 +693,9 @@ Audio trek seçimin göstərmək üçün \"Video axınları saxtalaşdır\"ı iO
<string name="revanced_hide_player_flyout_watch_in_vr_title">\"VR-da İzləni\" gizlət</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">\"VR-da İzləni\" gizlət</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">VR menyusunda izləmə gizlidir</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">VR menyusunda izləmə gizlidir</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">VR menyusunda izləmə göstərilir</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">VR menyusunda izləmə göstərilir</string>
<string name="revanced_hide_player_flyout_video_quality_title">Video keyfiyyət menyusunu gizlət</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">Video keyfiyyət menyusu gizlidir</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">Video keyfiyyət menyusu görünür</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Video keyfiyyət menyusu alt məlumatını gizlət</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">Video keyfiyyət menyusu alt məlumatını gizlət</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Video keyfiyyət menyusu alt məlumatı gizlidir</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Video keyfiyyət menyusu alt məlumatı gizlidir</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Video keyfiyyət menyusu alt məlumatı göstərilir</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Video keyfiyyət menyusu alt məlumatı göstərilir</string>
@@ -1464,7 +1467,10 @@ Bunu aktivləşdirmə daha yüksək video keyfiyyətləri əngəlin silə bilər
<string name="revanced_playback_speed_dialog_button_summary_on">Düymə göstərilir. Oynatma sürətin standart olaraq qaytarmaq üçün toxunub saxla</string> <string name="revanced_playback_speed_dialog_button_summary_on">Düymə göstərilir. Oynatma sürətin standart olaraq qaytarmaq üçün toxunub saxla</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Düymə göstərilmir</string> <string name="revanced_playback_speed_dialog_button_summary_off">Düymə göstərilmir</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Video keyfiyyəti düyməsini göstər</string>
<string name="revanced_video_quality_dialog_button_summary_on">Düymə görünür. Keyfiyyəti ilkin vəziyyətinə qaytarmaq üçün toxunub saxlayın</string>
<string name="revanced_video_quality_dialog_button_summary_off">Düymə görünmür</string>
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
<string name="revanced_custom_speed_menu_title">Fərdi oynatma sürəti siyahısı</string> <string name="revanced_custom_speed_menu_title">Fərdi oynatma sürəti siyahısı</string>

View File

@@ -693,6 +693,9 @@ Second \"item\" text"</string>
<string name="revanced_hide_player_flyout_watch_in_vr_title">Схаваць гадзіннік у VR</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">Схаваць гадзіннік у VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Меню прагляду ў VR схавана</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Меню прагляду ў VR схавана</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Паказана меню \"Глядзець у VR\"</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Паказана меню \"Глядзець у VR\"</string>
<string name="revanced_hide_player_flyout_video_quality_title">Схаваць меню якасці відэа</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">Меню якасці відэа схавана</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">Меню якасці відэа паказана</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Схаваць калонтытул меню якасці відэа</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">Схаваць калонтытул меню якасці відэа</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Ніжні калонтытул меню якасці відэа схаваны</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Ніжні калонтытул меню якасці відэа схаваны</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Паказваецца ніжні калонтытул меню якасці відэа</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Паказваецца ніжні калонтытул меню якасці відэа</string>
@@ -1466,7 +1469,7 @@ Second \"item\" text"</string>
<string name="revanced_playback_speed_dialog_button_summary_on">Кнопка паказана. Націсніце і ўтрымлівайце, каб скінуць хуткасць прайгравання да стандартнай</string> <string name="revanced_playback_speed_dialog_button_summary_on">Кнопка паказана. Націсніце і ўтрымлівайце, каб скінуць хуткасць прайгравання да стандартнай</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Кнопка не паказваецца</string> <string name="revanced_playback_speed_dialog_button_summary_off">Кнопка не паказваецца</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Паказаць кнопку якасці відэа</string> <string name="revanced_video_quality_dialog_button_title">Паказаць кнопку якасці відэа</string>
<string name="revanced_video_quality_dialog_button_summary_on">Кнопка паказана. Націсніце і ўтрымлівайце, каб скінуць якасць да па змаўчанні</string> <string name="revanced_video_quality_dialog_button_summary_on">Кнопка паказана. Націсніце і ўтрымлівайце, каб скінуць якасць да па змаўчанні</string>
<string name="revanced_video_quality_dialog_button_summary_off">Кнопка не паказваецца</string> <string name="revanced_video_quality_dialog_button_summary_off">Кнопка не паказваецца</string>

View File

@@ -693,6 +693,9 @@ Second \"item\" text"</string>
<string name="revanced_hide_player_flyout_watch_in_vr_title">Гледайте във VR</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">Гледайте във VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Менюто за гледане в VR е скрито</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Менюто за гледане в VR е скрито</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Менюто за гледане в VR се показва</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Менюто за гледане в VR се показва</string>
<string name="revanced_hide_player_flyout_video_quality_title">Скриване на менюто за качество на видеото</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">Менюто за качество на видеото е скрито</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">Менюто за качество на видеото е показано</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Скриване на футъра на менюто за качество на видеото</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">Скриване на футъра на менюто за качество на видеото</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Долният колонтитул на менюто за качество на видеото е скрит</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Долният колонтитул на менюто за качество на видеото е скрит</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Долният колонтитул на менюто за качество на видеото се показва</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Долният колонтитул на менюто за качество на видеото се показва</string>
@@ -1465,7 +1468,7 @@ Second \"item\" text"</string>
<string name="revanced_playback_speed_dialog_button_summary_on">Бутонът е показан. Докоснете и задръжте, за да върнете скоростта на възпроизвеждане към стойността по подразбиране</string> <string name="revanced_playback_speed_dialog_button_summary_on">Бутонът е показан. Докоснете и задръжте, за да върнете скоростта на възпроизвеждане към стойността по подразбиране</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Бутонът не е показан</string> <string name="revanced_playback_speed_dialog_button_summary_off">Бутонът не е показан</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Покажи бутона за качество на видеото</string> <string name="revanced_video_quality_dialog_button_title">Покажи бутона за качество на видеото</string>
<string name="revanced_video_quality_dialog_button_summary_on">Бутонът е показан. Докоснете и задръжте, за да възстановите качеството до подразбиране</string> <string name="revanced_video_quality_dialog_button_summary_on">Бутонът е показан. Докоснете и задръжте, за да възстановите качеството до подразбиране</string>
<string name="revanced_video_quality_dialog_button_summary_off">Бутонът не е показан</string> <string name="revanced_video_quality_dialog_button_summary_off">Бутонът не е показан</string>

View File

@@ -689,6 +689,9 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
<string name="revanced_hide_player_flyout_watch_in_vr_title">ভিআর-এ ঘড়ি লুকান</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">ভিআর-এ ঘড়ি লুকান</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">ভিআর মেনুতে দেখুন লুকানো আছে</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">ভিআর মেনুতে দেখুন লুকানো আছে</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">ভিআর মেনুতে দেখুন দেখানো হয়েছে</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">ভিআর মেনুতে দেখুন দেখানো হয়েছে</string>
<string name="revanced_hide_player_flyout_video_quality_title">ভিডিও গুণমান মেনু লুকান</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">ভিডিও মানের মেনু লুকানো আছে</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">ভিডিও মানের মেনু দেখানো হয়েছে</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">ভিডিও গুণমান মেনুর ফুটার লুকান</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">ভিডিও গুণমান মেনুর ফুটার লুকান</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">ভিডিও গুণমান মেনু ফুটার লুকানো আছে</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">ভিডিও গুণমান মেনু ফুটার লুকানো আছে</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">ভিডিও গুণমান মেনু ফুটার দেখানো হচ্ছে</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">ভিডিও গুণমান মেনু ফুটার দেখানো হচ্ছে</string>
@@ -1461,7 +1464,7 @@ DeArrow সম্পর্কে আরও জানতে এখানে ট
<string name="revanced_playback_speed_dialog_button_summary_on">বোতামটি দেখানো হয়েছে। প্লেব্যাক স্পীড ডিফল্টে রিসেট করতে ট্যাপ করে ধরে রাখুন।</string> <string name="revanced_playback_speed_dialog_button_summary_on">বোতামটি দেখানো হয়েছে। প্লেব্যাক স্পীড ডিফল্টে রিসেট করতে ট্যাপ করে ধরে রাখুন।</string>
<string name="revanced_playback_speed_dialog_button_summary_off">বোতাম প্রদর্শিত হয়নি</string> <string name="revanced_playback_speed_dialog_button_summary_off">বোতাম প্রদর্শিত হয়নি</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">ভিডিও গুণমান বোতাম দেখান</string> <string name="revanced_video_quality_dialog_button_title">ভিডিও গুণমান বোতাম দেখান</string>
<string name="revanced_video_quality_dialog_button_summary_on">বোতামটি দেখানো হয়েছে। গুণমান ডিফল্টে রিসেট করতে ট্যাপ করে ধরে রাখুন।</string> <string name="revanced_video_quality_dialog_button_summary_on">বোতামটি দেখানো হয়েছে। গুণমান ডিফল্টে রিসেট করতে ট্যাপ করে ধরে রাখুন।</string>
<string name="revanced_video_quality_dialog_button_summary_off">বোতামটি দেখানো হয়নি।</string> <string name="revanced_video_quality_dialog_button_summary_off">বোতামটি দেখানো হয়নি।</string>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -693,6 +693,9 @@ Chcete-li zobrazit nabídku zvukové stopy, změňte možnost „Zfalšovat stre
<string name="revanced_hide_player_flyout_watch_in_vr_title">Skrýt Sledovat ve VR</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">Skrýt Sledovat ve VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Menu Sledovat ve VR je skryto</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Menu Sledovat ve VR je skryto</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Menu Sledovat ve VR je zobrazeno</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Menu Sledovat ve VR je zobrazeno</string>
<string name="revanced_hide_player_flyout_video_quality_title">Skrýt nabídku kvality videa</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">Nabídka kvality videa je skryta</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">Nabídka kvality videa je zobrazena</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Skrýt zápatí menu kvality videa</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">Skrýt zápatí menu kvality videa</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Zápatí menu kvality videa je skryto</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Zápatí menu kvality videa je skryto</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Zápatí menu kvality videa je zobrazeno</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Zápatí menu kvality videa je zobrazeno</string>
@@ -1465,7 +1468,7 @@ Povolením této funkce lze odemknout vyšší kvality videa"</string>
<string name="revanced_playback_speed_dialog_button_summary_on">Tlačítko je zobrazeno. Klepnutím a podržením obnovíte výchozí rychlost přehrávání</string> <string name="revanced_playback_speed_dialog_button_summary_on">Tlačítko je zobrazeno. Klepnutím a podržením obnovíte výchozí rychlost přehrávání</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Tlačítko se nezobrazuje</string> <string name="revanced_playback_speed_dialog_button_summary_off">Tlačítko se nezobrazuje</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Zobrazit tlačítko kvality videa</string> <string name="revanced_video_quality_dialog_button_title">Zobrazit tlačítko kvality videa</string>
<string name="revanced_video_quality_dialog_button_summary_on">Tlačítko je zobrazeno. Klepnutím a podržením obnovíte kvalitu na výchozí</string> <string name="revanced_video_quality_dialog_button_summary_on">Tlačítko je zobrazeno. Klepnutím a podržením obnovíte kvalitu na výchozí</string>
<string name="revanced_video_quality_dialog_button_summary_off">Tlačítko není zobrazeno.</string> <string name="revanced_video_quality_dialog_button_summary_off">Tlačítko není zobrazeno.</string>

View File

@@ -693,6 +693,9 @@ For at vise lydspormenuen skal du ændre \"Spoof videostream\" til iOS TV"</stri
<string name="revanced_hide_player_flyout_watch_in_vr_title">Skjul vagt i VR</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">Skjul vagt i VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Se i VR-menuen er skjult</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Se i VR-menuen er skjult</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Se i VR-menuen vises</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Se i VR-menuen vises</string>
<string name="revanced_hide_player_flyout_video_quality_title">Skjul menu for videokvalitet</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">Videokvalitetsmenuen er skjult</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">Videokvalitetsmenuen vises</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Skjul sidefod til videokvalitet</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">Skjul sidefod til videokvalitet</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Videokvalitetsmenuens sidefod er skjult</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Videokvalitetsmenuens sidefod er skjult</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Videokvalitet menu footer er vist</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Videokvalitet menu footer er vist</string>
@@ -1467,7 +1470,7 @@ Aktivering af dette kan låse op for højere videokvalitet"</string>
<string name="revanced_playback_speed_dialog_button_summary_on">Knappen vises. Tryk og hold for at nulstille afspilningshastigheden til standard.</string> <string name="revanced_playback_speed_dialog_button_summary_on">Knappen vises. Tryk og hold for at nulstille afspilningshastigheden til standard.</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Knap vises ikke</string> <string name="revanced_playback_speed_dialog_button_summary_off">Knap vises ikke</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Vis videokvalitetsknap</string> <string name="revanced_video_quality_dialog_button_title">Vis videokvalitetsknap</string>
<string name="revanced_video_quality_dialog_button_summary_on">Knap vises. Tryk og hold nede for at nulstille kvaliteten til standard</string> <string name="revanced_video_quality_dialog_button_summary_on">Knap vises. Tryk og hold nede for at nulstille kvaliteten til standard</string>
<string name="revanced_video_quality_dialog_button_summary_off">Knappen vises ikke</string> <string name="revanced_video_quality_dialog_button_summary_off">Knappen vises ikke</string>

View File

@@ -688,6 +688,9 @@ Um das Audiotrack-Menü anzuzeigen, ändere \"Video-Streams fälschen\" zu iOS T
<string name="revanced_hide_player_flyout_watch_in_vr_title">Überwachung in VR ausblenden</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">Überwachung in VR ausblenden</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Im VR-Menü beobachten ist ausgeblendet</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Im VR-Menü beobachten ist ausgeblendet</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Im VR-Menü beobachten wird angezeigt</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Im VR-Menü beobachten wird angezeigt</string>
<string name="revanced_hide_player_flyout_video_quality_title">Videoqualitätsmenü ausblenden</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">Videomenü ist ausgeblendet</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">Videomenü ist sichtbar</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Videoqualitätsmenüfußzeile ausblenden</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">Videoqualitätsmenüfußzeile ausblenden</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Video-Qualität Menü-Fußzeile ist ausgeblendet</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Video-Qualität Menü-Fußzeile ist ausgeblendet</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Video-Qualität Menü-Fußzeile wird angezeigt</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Video-Qualität Menü-Fußzeile wird angezeigt</string>
@@ -1460,7 +1463,7 @@ Durch Aktivieren dieser Option können höhere Videoqualitäten freigeschaltet w
<string name="revanced_playback_speed_dialog_button_summary_on">Die Schaltfläche wird angezeigt. Tippen und halten, um die Wiedergabegeschwindigkeit auf die Standardeinstellung zurückzusetzen.</string> <string name="revanced_playback_speed_dialog_button_summary_on">Die Schaltfläche wird angezeigt. Tippen und halten, um die Wiedergabegeschwindigkeit auf die Standardeinstellung zurückzusetzen.</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Button wird nicht angezeigt</string> <string name="revanced_playback_speed_dialog_button_summary_off">Button wird nicht angezeigt</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Videoqualität-Schaltfläche anzeigen</string> <string name="revanced_video_quality_dialog_button_title">Videoqualität-Schaltfläche anzeigen</string>
<string name="revanced_video_quality_dialog_button_summary_on">Schaltfläche wird angezeigt. Tippen und halten, um die Qualität auf Standard zurückzusetzen</string> <string name="revanced_video_quality_dialog_button_summary_on">Schaltfläche wird angezeigt. Tippen und halten, um die Qualität auf Standard zurückzusetzen</string>
<string name="revanced_video_quality_dialog_button_summary_off">Schaltfläche wird nicht angezeigt</string> <string name="revanced_video_quality_dialog_button_summary_off">Schaltfläche wird nicht angezeigt</string>

View File

@@ -695,6 +695,9 @@ Second \"item\" text"</string>
<string name="revanced_hide_player_flyout_watch_in_vr_title">Μενού «Προβολή σε VR»</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">Μενού «Προβολή σε VR»</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Κρυμμένο</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Κρυμμένο</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Εμφανίζεται</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Εμφανίζεται</string>
<string name="revanced_hide_player_flyout_video_quality_title">Μενού «Ποιότητα»</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">Κρυμμένο</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">Εμφανίζεται</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Οδηγίες του μενού ποιότητας βίντεο</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">Οδηγίες του μενού ποιότητας βίντεο</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Κρυμμένες</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Κρυμμένες</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Εμφανίζονται</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Εμφανίζονται</string>
@@ -1464,7 +1467,7 @@ Second \"item\" text"</string>
<string name="revanced_playback_speed_dialog_button_summary_on">Το κουμπί εμφανίζεται. Πατήστε παρατεταμένα για επαναφορά της ταχύτητας αναπαραγωγής στην προεπιλογή</string> <string name="revanced_playback_speed_dialog_button_summary_on">Το κουμπί εμφανίζεται. Πατήστε παρατεταμένα για επαναφορά της ταχύτητας αναπαραγωγής στην προεπιλογή</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Το κουμπί δεν εμφανίζεται</string> <string name="revanced_playback_speed_dialog_button_summary_off">Το κουμπί δεν εμφανίζεται</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Εμφάνιση κουμπιού αλλαγής ποιότητας βίντεο</string> <string name="revanced_video_quality_dialog_button_title">Εμφάνιση κουμπιού αλλαγής ποιότητας βίντεο</string>
<string name="revanced_video_quality_dialog_button_summary_on">Το κουμπί εμφανίζεται. Πατήστε παρατεταμένα για επαναφορά της ποιότητας στην προεπιλογή</string> <string name="revanced_video_quality_dialog_button_summary_on">Το κουμπί εμφανίζεται. Πατήστε παρατεταμένα για επαναφορά της ποιότητας στην προεπιλογή</string>
<string name="revanced_video_quality_dialog_button_summary_off">Το κουμπί δεν εμφανίζεται</string> <string name="revanced_video_quality_dialog_button_summary_off">Το κουμπί δεν εμφανίζεται</string>

View File

@@ -693,6 +693,9 @@ Para mostrar el menú de la pista de audio, cambia \"Suplantar transmisiones de
<string name="revanced_hide_player_flyout_watch_in_vr_title">Ocultar reloj en VR</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">Ocultar reloj en VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Ver en el menú VR está oculto</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Ver en el menú VR está oculto</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Ver en el menú VR se muestra</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Ver en el menú VR se muestra</string>
<string name="revanced_hide_player_flyout_video_quality_title">Ocultar menú de calidad de vídeo</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">El menú de calidad de video está oculto</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">El menú de calidad de video está visible</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Ocultar pie de página del menú de calidad de vídeo</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">Ocultar pie de página del menú de calidad de vídeo</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Pie de menú de calidad de vídeo oculto</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Pie de menú de calidad de vídeo oculto</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">El pie del menú de calidad de vídeo se muestra</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">El pie del menú de calidad de vídeo se muestra</string>
@@ -1456,7 +1459,7 @@ Habilitar esto puede desbloquear calidades de vídeo más altas"</string>
<string name="revanced_playback_speed_dialog_button_summary_on">Se muestra el botón. Mantén pulsado para restablecer la velocidad de reproducción predeterminada</string> <string name="revanced_playback_speed_dialog_button_summary_on">Se muestra el botón. Mantén pulsado para restablecer la velocidad de reproducción predeterminada</string>
<string name="revanced_playback_speed_dialog_button_summary_off">El botón no se muestra</string> <string name="revanced_playback_speed_dialog_button_summary_off">El botón no se muestra</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Mostrar botón de calidad de video</string> <string name="revanced_video_quality_dialog_button_title">Mostrar botón de calidad de video</string>
<string name="revanced_video_quality_dialog_button_summary_on">Botón visible. Toca y mantén para restablecer la calidad a los valores predeterminados</string> <string name="revanced_video_quality_dialog_button_summary_on">Botón visible. Toca y mantén para restablecer la calidad a los valores predeterminados</string>
<string name="revanced_video_quality_dialog_button_summary_off">Botón no visible</string> <string name="revanced_video_quality_dialog_button_summary_off">Botón no visible</string>

View File

@@ -693,6 +693,9 @@ Heliriba menüü kuvamiseks muutke valikut „Võltsitud videovoogedastus“ vä
<string name="revanced_hide_player_flyout_watch_in_vr_title">Peida Vaata VR-is</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">Peida Vaata VR-is</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Vaata VR-is menüü on peidetud</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Vaata VR-is menüü on peidetud</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Vaata VR-is menüü on nähtav</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Vaata VR-is menüü on nähtav</string>
<string name="revanced_hide_player_flyout_video_quality_title">Peida videokvaliteedi menüü</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">Videokvaliteedi menüü on peidetud</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">Videokvaliteedi menüü on nähtav</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Peida video kvaliteedi menüü jalg</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">Peida video kvaliteedi menüü jalg</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Video kvaliteedi menüü jalg on peidetud</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Video kvaliteedi menüü jalg on peidetud</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Video kvaliteedi menüü jalg on nähtav</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Video kvaliteedi menüü jalg on nähtav</string>
@@ -1465,7 +1468,7 @@ Selle lubamine võib avada kõrgema video kvaliteedi"</string>
<string name="revanced_playback_speed_dialog_button_summary_on">Nupp on nähtaval. Puudutage ja hoidke all, et taastada taasesituse kiirus vaikeväärtusele</string> <string name="revanced_playback_speed_dialog_button_summary_on">Nupp on nähtaval. Puudutage ja hoidke all, et taastada taasesituse kiirus vaikeväärtusele</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Nuppi ei kuvata</string> <string name="revanced_playback_speed_dialog_button_summary_off">Nuppi ei kuvata</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Näita video kvaliteedi nuppu</string> <string name="revanced_video_quality_dialog_button_title">Näita video kvaliteedi nuppu</string>
<string name="revanced_video_quality_dialog_button_summary_on">Nupp on nähtaval. Kvaliteedi lähtestamiseks vaikeseadeteks puudutage ja hoidke</string> <string name="revanced_video_quality_dialog_button_summary_on">Nupp on nähtaval. Kvaliteedi lähtestamiseks vaikeseadeteks puudutage ja hoidke</string>
<string name="revanced_video_quality_dialog_button_summary_off">Nuppu ei kuvata</string> <string name="revanced_video_quality_dialog_button_summary_off">Nuppu ei kuvata</string>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -272,7 +272,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -1465,7 +1465,10 @@ Tämä voi avata korkealaatuisemmat videot"</string>
<string name="revanced_playback_speed_dialog_button_summary_on">Painike näytetään. Napauta ja pidä pohjassa palauttaaksesi soiton nopeuden oletukseksi</string> <string name="revanced_playback_speed_dialog_button_summary_on">Painike näytetään. Napauta ja pidä pohjassa palauttaaksesi soiton nopeuden oletukseksi</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Painiketta ei näytetä</string> <string name="revanced_playback_speed_dialog_button_summary_off">Painiketta ei näytetä</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Näytä videolaatupainike</string>
<string name="revanced_video_quality_dialog_button_summary_on">Painike näkyy. Paina pitkään palauttaaksesi laadun oletukseksi</string>
<string name="revanced_video_quality_dialog_button_summary_off">Painiketta ei näytetä</string>
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
<string name="revanced_custom_speed_menu_title">Mukautettu toistonopeusvalikko</string> <string name="revanced_custom_speed_menu_title">Mukautettu toistonopeusvalikko</string>

View File

@@ -691,6 +691,9 @@ Upang ipakita ang menu ng Audio track, baguhin ang 'Spoof video streams' sa iOS
<string name="revanced_hide_player_flyout_watch_in_vr_title">Itago ang Panoorin sa VR</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">Itago ang Panoorin sa VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Nakatago ang panonood sa VR menu</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Nakatago ang panonood sa VR menu</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Ang panonood sa VR menu ay ipinapakita</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Ang panonood sa VR menu ay ipinapakita</string>
<string name="revanced_hide_player_flyout_video_quality_title">Itago ang menu ng kalidad ng video</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">Nakatago ang menu ng kalidad ng video</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">Ipinapakita ang menu ng kalidad ng video</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Itago ang footer ng menu ng kalidad ng video</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">Itago ang footer ng menu ng kalidad ng video</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Nakatago ang footer ng menu ng kalidad ng video</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Nakatago ang footer ng menu ng kalidad ng video</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Ang footer ng menu ng kalidad ng video ay ipinapakita</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Ang footer ng menu ng kalidad ng video ay ipinapakita</string>
@@ -1463,7 +1466,7 @@ Ang pagpapagana nito ay maaaring magbukas ng mas mataas na kalidad ng video"</st
<string name="revanced_playback_speed_dialog_button_summary_on">Ipinapakita ang button. I-tap at i-hold para i-reset ang bilis ng pag-playback sa default</string> <string name="revanced_playback_speed_dialog_button_summary_on">Ipinapakita ang button. I-tap at i-hold para i-reset ang bilis ng pag-playback sa default</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Hindi ipinapakita ang button</string> <string name="revanced_playback_speed_dialog_button_summary_off">Hindi ipinapakita ang button</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Ipakita ang button ng kalidad ng video</string> <string name="revanced_video_quality_dialog_button_title">Ipakita ang button ng kalidad ng video</string>
<string name="revanced_video_quality_dialog_button_summary_on">Nakalabas ang button. Pindutin nang matagal para ibalik sa default ang kalidad</string> <string name="revanced_video_quality_dialog_button_summary_on">Nakalabas ang button. Pindutin nang matagal para ibalik sa default ang kalidad</string>
<string name="revanced_video_quality_dialog_button_summary_off">Hindi ipinapakita ang buton</string> <string name="revanced_video_quality_dialog_button_summary_off">Hindi ipinapakita ang buton</string>

View File

@@ -693,6 +693,9 @@ Pour afficher le menu Piste audio, définissez \"Falsifier les flux vidéo\" sur
<string name="revanced_hide_player_flyout_watch_in_vr_title">Masquer \"Regarder en RV\"</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">Masquer \"Regarder en RV\"</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Le menu Regarder en RV est masqué</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Le menu Regarder en RV est masqué</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Le menu Regarder en RV est affiché</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Le menu Regarder en RV est affiché</string>
<string name="revanced_hide_player_flyout_video_quality_title">Masquer le menu de qualité vidéo</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">Le menu de qualité vidéo est masqué</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">Le menu de qualité vidéo est affiché</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Masquer le pied de page du menu de qualité vidéo</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">Masquer le pied de page du menu de qualité vidéo</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Le pied de page du menu de qualité vidéo est masqué</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Le pied de page du menu de qualité vidéo est masqué</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Le pied de page du menu de qualité vidéo est affiché</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Le pied de page du menu de qualité vidéo est affiché</string>
@@ -1466,9 +1469,9 @@ Activer cette option peut déverrouiller des qualités vidéo supérieures"</str
<string name="revanced_playback_speed_dialog_button_summary_on">Le bouton est affiché. Appuyez longuement dessus pour rétablir la vitesse de lecture par défaut.</string> <string name="revanced_playback_speed_dialog_button_summary_on">Le bouton est affiché. Appuyez longuement dessus pour rétablir la vitesse de lecture par défaut.</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Le bouton n\'est pas affiché</string> <string name="revanced_playback_speed_dialog_button_summary_off">Le bouton n\'est pas affiché</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Afficher le bouton de qualité vidéo</string> <string name="revanced_video_quality_dialog_button_title">Afficher le bouton de qualité vidéo</string>
<string name="revanced_video_quality_dialog_button_summary_on">Le bouton est affiché. Appuyez longuement pour réinitialiser la qualité par défaut</string> <string name="revanced_video_quality_dialog_button_summary_on">Le bouton est affiché. Appuyez longuement pour rétablir la qualité par défaut.</string>
<string name="revanced_video_quality_dialog_button_summary_off">Le bouton n\'est pas affiché</string> <string name="revanced_video_quality_dialog_button_summary_off">Le bouton n\'est pas affiché</string>
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">

View File

@@ -693,6 +693,9 @@ Chun roghchlár na rian fuaime a thaispeáint, athraigh 'Srutháin físeáin bhr
<string name="revanced_hide_player_flyout_watch_in_vr_title">Folaigh Watch i VR</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">Folaigh Watch i VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Tá faire i roghchlár VR i bhfolach</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Tá faire i roghchlár VR i bhfolach</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Taispeántar an faire sa roghchlár VR</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Taispeántar an faire sa roghchlár VR</string>
<string name="revanced_hide_player_flyout_video_quality_title">Folaigh roghchlár cáilíocht físe</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">Tá roghchlár cháilíocht na físeáin i bhfolach</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">Tá roghchlár cháilíocht na físeáin ar taispeáint</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Folaigh buntásc roghchlár cáilíochta físe</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">Folaigh buntásc roghchlár cáilíochta físe</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Tá buntásc an roghchláir cáilíochta físeáin folaithe</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Tá buntásc an roghchláir cáilíochta físeáin folaithe</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Taispeántar buntásc roghchlár cáilíochta físeáin</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Taispeántar buntásc roghchlár cáilíochta físeáin</string>
@@ -1465,7 +1468,7 @@ Is féidir le seo caighdeáin físeáin níos airde a dhíghlasáil"</string>
<string name="revanced_playback_speed_dialog_button_summary_on">Taispeántar an cnaipe. Tapáil agus coinnigh chun luas athsheinm a athshocrú go réamhshocrú</string> <string name="revanced_playback_speed_dialog_button_summary_on">Taispeántar an cnaipe. Tapáil agus coinnigh chun luas athsheinm a athshocrú go réamhshocrú</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Ní thaispeántar an cnaipe</string> <string name="revanced_playback_speed_dialog_button_summary_off">Ní thaispeántar an cnaipe</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Taispeáin cnaipe cáilíochta físeáin</string> <string name="revanced_video_quality_dialog_button_title">Taispeáin cnaipe cáilíochta físeáin</string>
<string name="revanced_video_quality_dialog_button_summary_on">Tá cnaipe le feiceáil. Tapáil agus coinnigh chun cáilíocht a athshocrú mar réamhshocrú</string> <string name="revanced_video_quality_dialog_button_summary_on">Tá cnaipe le feiceáil. Tapáil agus coinnigh chun cáilíocht a athshocrú mar réamhshocrú</string>
<string name="revanced_video_quality_dialog_button_summary_off">Níl cnaipe le feiceáil</string> <string name="revanced_video_quality_dialog_button_summary_off">Níl cnaipe le feiceáil</string>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -693,6 +693,9 @@ Az audiosáv menü megjelenítéséhez módosítsa a \"Videófolyamok hamisítá
<string name="revanced_hide_player_flyout_watch_in_vr_title">\"Megtekintés VR-módban\" elrejtése</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">\"Megtekintés VR-módban\" elrejtése</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">A megtekintés VR-módban menü el van rejtve</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">A megtekintés VR-módban menü el van rejtve</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">A „Megtekintés VR-módban” menü megjelenik</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">A „Megtekintés VR-módban” menü megjelenik</string>
<string name="revanced_hide_player_flyout_video_quality_title">Videóminőség menü elrejtése</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">A videóminőség menü elrejtve</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">A videóminőség menü megjelenítve</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">A videóminőség menü láblécének elrejtése</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">A videóminőség menü láblécének elrejtése</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">A videóminőség menü lábléce el van rejtve</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">A videóminőség menü lábléce el van rejtve</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Megjelenik a videóminőség menü lábléce</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Megjelenik a videóminőség menü lábléce</string>
@@ -1462,7 +1465,7 @@ Ez a beállítás lehetővé teszi a magasabb videóminőségek feloldását"</s
<string name="revanced_playback_speed_dialog_button_summary_on">A gomb látható. Tartsa lenyomva a lejátszási sebesség alapértelmezettre állításához</string> <string name="revanced_playback_speed_dialog_button_summary_on">A gomb látható. Tartsa lenyomva a lejátszási sebesség alapértelmezettre állításához</string>
<string name="revanced_playback_speed_dialog_button_summary_off">A gomb nem látható</string> <string name="revanced_playback_speed_dialog_button_summary_off">A gomb nem látható</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Videóminőség gomb megjelenítése</string> <string name="revanced_video_quality_dialog_button_title">Videóminőség gomb megjelenítése</string>
<string name="revanced_video_quality_dialog_button_summary_on">A gomb látható. Tartsa lenyomva a minőséget az alapértelmezettre visszaállításához</string> <string name="revanced_video_quality_dialog_button_summary_on">A gomb látható. Tartsa lenyomva a minőséget az alapértelmezettre visszaállításához</string>
<string name="revanced_video_quality_dialog_button_summary_off">A gomb nem látható</string> <string name="revanced_video_quality_dialog_button_summary_off">A gomb nem látható</string>

View File

@@ -693,6 +693,9 @@ MicroG-ի համար մարտկոցի օպտիմալացումը անջատել
<string name="revanced_hide_player_flyout_watch_in_vr_title">Դիտել VR-ով թաքցնել</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">Դիտել VR-ով թաքցնել</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">VR-ով դիտել մենյուը թաքցված է</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">VR-ով դիտել մենյուը թաքցված է</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">VR-ով դիտել մենյուը երևում է</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">VR-ով դիտել մենյուը երևում է</string>
<string name="revanced_hide_player_flyout_video_quality_title">Թաքցնել տեսանյութի որակի ընտրացանկը</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">Տեսանյութի որակի ընտրացանկը թաքնված է</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">Տեսանյութի որակի ընտրացանկը ցուցադրված է</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Տեսանյութի որակի մենյուի ստորագրությունը թաքցնել</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">Տեսանյութի որակի մենյուի ստորագրությունը թաքցնել</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Տեսանյութի որակի մենյուի ստորագրությունը թաքցված է</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Տեսանյութի որակի մենյուի ստորագրությունը թաքցված է</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Տեսանյութի որակի մենյուի ստորագրությունը երևում է</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Տեսանյութի որակի մենյուի ստորագրությունը երևում է</string>
@@ -1466,9 +1469,9 @@ Mini-player-ը կարող է գրավվել էկրանից դուրս՝ դեպի
<string name="revanced_playback_speed_dialog_button_summary_on">Կոճակը ցուցադրվում է: Հպեք և պահեք՝ նվագարկման արագությունը լռելյայնի վերականգնելու համար</string> <string name="revanced_playback_speed_dialog_button_summary_on">Կոճակը ցուցադրվում է: Հպեք և պահեք՝ նվագարկման արագությունը լռելյայնի վերականգնելու համար</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Կոճակը չի ցուցադրվում</string> <string name="revanced_playback_speed_dialog_button_summary_off">Կոճակը չի ցուցադրվում</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Ցուցադրել տեսանյութի որակի կոճակը</string> <string name="revanced_video_quality_dialog_button_title">Ցուցադրել տեսանյութի որակի կոճակը</string>
<string name="revanced_video_quality_dialog_button_summary_on">Կոճակը ցուցադրված է։ Սեղմեք և պահեք՝ որակը լռելյայն վիճակի վերականգնելու համար</string> <string name="revanced_video_quality_dialog_button_summary_on">Կոճակը ցուցադրված է։ Հպեք և պահեք՝ որակը լռելյայնին վերականգնելու համար</string>
<string name="revanced_video_quality_dialog_button_summary_off">Կոճակը ցուցադրված չէ։</string> <string name="revanced_video_quality_dialog_button_summary_off">Կոճակը ցուցադրված չէ։</string>
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">

View File

@@ -693,6 +693,9 @@ Untuk menampilkan menu trek Audio, ubah 'Spoof aliran video' ke iOS TV"</string>
<string name="revanced_hide_player_flyout_watch_in_vr_title">Sembunyikan Tonton di VR</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">Sembunyikan Tonton di VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Menu tonton di VR disembunyikan</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Menu tonton di VR disembunyikan</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Menu tonton di VR ditampilkan</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Menu tonton di VR ditampilkan</string>
<string name="revanced_hide_player_flyout_video_quality_title">Sembunyikan menu kualitas video</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">Menu kualitas video disembunyikan</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">Menu kualitas video ditampilkan</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Sembunyikan footer menu kualitas video</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">Sembunyikan footer menu kualitas video</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Footer menu kualitas video disembunyikan</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Footer menu kualitas video disembunyikan</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Footer menu kualitas video ditampilkan</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Footer menu kualitas video ditampilkan</string>
@@ -1464,9 +1467,9 @@ Mengaktifkan ini dapat membuka kualitas video yang lebih tinggi"</string>
<string name="revanced_playback_speed_dialog_button_summary_on">Tombol ditampilkan. Ketuk dan tahan untuk mengatur ulang kecepatan pemutaran ke bawaan</string> <string name="revanced_playback_speed_dialog_button_summary_on">Tombol ditampilkan. Ketuk dan tahan untuk mengatur ulang kecepatan pemutaran ke bawaan</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Tombol tidak ditampilkan</string> <string name="revanced_playback_speed_dialog_button_summary_off">Tombol tidak ditampilkan</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Tampilkan tombol kualitas video</string> <string name="revanced_video_quality_dialog_button_title">Tampilkan tombol kualitas video</string>
<string name="revanced_video_quality_dialog_button_summary_on">Tombol ditampilkan. Ketuk dan tahan untuk mengatur ulang kualitas ke default</string> <string name="revanced_video_quality_dialog_button_summary_on">Tombol ditampilkan. Ketuk dan tahan untuk mengatur ulang kualitas ke bawaan</string>
<string name="revanced_video_quality_dialog_button_summary_off">Tombol tidak ditampilkan</string> <string name="revanced_video_quality_dialog_button_summary_off">Tombol tidak ditampilkan</string>
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -693,6 +693,9 @@ Per mostrare il menu della traccia audio, cambia \"Spoof video streams\" in iOS
<string name="revanced_hide_player_flyout_watch_in_vr_title">Nascondi Guarda in VR</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">Nascondi Guarda in VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Il menu Guarda in VR è nascosto</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Il menu Guarda in VR è nascosto</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Il menu Guarda in VR è visibile</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Il menu Guarda in VR è visibile</string>
<string name="revanced_hide_player_flyout_video_quality_title">Nascondi menu qualità video</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">Il menu della qualità video è nascosto</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">Il menu della qualità video è visualizzato</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Nascondi piè di pagina del menu qualità video</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">Nascondi piè di pagina del menu qualità video</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Il piè di pagina del menu di qualità video è nascosto</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Il piè di pagina del menu di qualità video è nascosto</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Il piè di pagina del menu di qualità video è visibile</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Il piè di pagina del menu di qualità video è visibile</string>
@@ -1464,9 +1467,9 @@ Abilitare questa opzione può sbloccare qualità video più elevate"</string>
<string name="revanced_playback_speed_dialog_button_summary_on">Il pulsante è visualizzato. Tieni premuto per ripristinare la velocità di riproduzione predefinita</string> <string name="revanced_playback_speed_dialog_button_summary_on">Il pulsante è visualizzato. Tieni premuto per ripristinare la velocità di riproduzione predefinita</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Il pulsante non è visibile</string> <string name="revanced_playback_speed_dialog_button_summary_off">Il pulsante non è visibile</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Mostra il pulsante qualità video</string> <string name="revanced_video_quality_dialog_button_title">Mostra il pulsante qualità video</string>
<string name="revanced_video_quality_dialog_button_summary_on">Il pulsante è visibile. Tocca e tieni premuto per ripristinare la qualità predefinita.</string> <string name="revanced_video_quality_dialog_button_summary_on">Il pulsante è visualizzato. Tocca e tieni premuto per ripristinare la qualità predefinita</string>
<string name="revanced_video_quality_dialog_button_summary_off">Il pulsante non è visibile.</string> <string name="revanced_video_quality_dialog_button_summary_off">Il pulsante non è visibile.</string>
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">

View File

@@ -693,6 +693,9 @@ Second \"item\" text"</string>
<string name="revanced_hide_player_flyout_watch_in_vr_title">הסתר \'צפה ב-VR\'</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">הסתר \'צפה ב-VR\'</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">תפריט \'צפה ב-VR\' מוסתר</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">תפריט \'צפה ב-VR\' מוסתר</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">תפריט \'צפה ב-VR\' מוצג</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">תפריט \'צפה ב-VR\' מוצג</string>
<string name="revanced_hide_player_flyout_video_quality_title">הסתר תפריט איכות וידאו</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">תפריט איכות הסרטון מוסתר</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">תפריט איכות הסרטון מוצג</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">הסתר כותרת תחתונה של תפריט איכות סרטון</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">הסתר כותרת תחתונה של תפריט איכות סרטון</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">כותרת תחתונה של תפריט איכות סרטון מוסתרת</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">כותרת תחתונה של תפריט איכות סרטון מוסתרת</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">כותרת תחתונה של תפריט איכות סרטון מוצגת</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">כותרת תחתונה של תפריט איכות סרטון מוצגת</string>
@@ -1467,7 +1470,7 @@ Second \"item\" text"</string>
<string name="revanced_playback_speed_dialog_button_summary_on">הלחצן מוצג. יש להקיש ולהחזיק כדי לאפס את מהירות ההפעלה לברירת מחדל</string> <string name="revanced_playback_speed_dialog_button_summary_on">הלחצן מוצג. יש להקיש ולהחזיק כדי לאפס את מהירות ההפעלה לברירת מחדל</string>
<string name="revanced_playback_speed_dialog_button_summary_off">הלחצן אינו מוצג</string> <string name="revanced_playback_speed_dialog_button_summary_off">הלחצן אינו מוצג</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">הצג כפתור איכות וידאו</string> <string name="revanced_video_quality_dialog_button_title">הצג כפתור איכות וידאו</string>
<string name="revanced_video_quality_dialog_button_summary_on">הלחצן מוצג. גע והחזק כדי לאפס את האיכות לברירת מחדל</string> <string name="revanced_video_quality_dialog_button_summary_on">הלחצן מוצג. גע והחזק כדי לאפס את האיכות לברירת מחדל</string>
<string name="revanced_video_quality_dialog_button_summary_off">הלחצן אינו מוצג</string> <string name="revanced_video_quality_dialog_button_summary_off">הלחצן אינו מוצג</string>

View File

@@ -107,8 +107,8 @@ GmsCore の電池の最適化を無効にしても、バッテリーの使用に
</patch> </patch>
<patch id="misc.backgroundplayback.backgroundPlaybackPatch"> <patch id="misc.backgroundplayback.backgroundPlaybackPatch">
<string name="revanced_shorts_disable_background_playback_title">ショートのバックグラウンド再生を無効化</string> <string name="revanced_shorts_disable_background_playback_title">ショートのバックグラウンド再生を無効化</string>
<string name="revanced_shorts_disable_background_playback_summary_on">ショートのバックグラウンド再生は無効です</string> <string name="revanced_shorts_disable_background_playback_summary_on">ショート動画のバックグラウンド再生は無効です</string>
<string name="revanced_shorts_disable_background_playback_summary_off">ショートのバックグラウンド再生は有効です</string> <string name="revanced_shorts_disable_background_playback_summary_off">ショート動画のバックグラウンド再生は有効です</string>
</patch> </patch>
<patch id="misc.debugging.enableDebuggingPatch"> <patch id="misc.debugging.enableDebuggingPatch">
<string name="revanced_debug_screen_title">デバッグ</string> <string name="revanced_debug_screen_title">デバッグ</string>
@@ -301,9 +301,9 @@ GmsCore の電池の最適化を無効にしても、バッテリーの使用に
<string name="revanced_hide_for_you_shelf_title">「おすすめ」欄を非表示</string> <string name="revanced_hide_for_you_shelf_title">「おすすめ」欄を非表示</string>
<string name="revanced_hide_for_you_shelf_summary_on">「おすすめ」欄は表示されません</string> <string name="revanced_hide_for_you_shelf_summary_on">「おすすめ」欄は表示されません</string>
<string name="revanced_hide_for_you_shelf_summary_off">「おすすめ」欄は表示されます</string> <string name="revanced_hide_for_you_shelf_summary_off">「おすすめ」欄は表示されます</string>
<string name="revanced_hide_links_preview_title">リンクのプレビューを非表示</string> <string name="revanced_hide_links_preview_title">リンクのプレビューを非表示</string>
<string name="revanced_hide_links_preview_summary_on">リンクのプレビューは表示されません</string> <string name="revanced_hide_links_preview_summary_on">リンクのプレビューは表示されません</string>
<string name="revanced_hide_links_preview_summary_off">リンクのプレビューは表示されます</string> <string name="revanced_hide_links_preview_summary_off">リンクのプレビューは表示されます</string>
<string name="revanced_hide_members_shelf_title">メンバー欄を非表示</string> <string name="revanced_hide_members_shelf_title">メンバー欄を非表示</string>
<string name="revanced_hide_members_shelf_summary_on">メンバー欄は表示されません</string> <string name="revanced_hide_members_shelf_summary_on">メンバー欄は表示されません</string>
<string name="revanced_hide_members_shelf_summary_off">メンバー欄は表示されます</string> <string name="revanced_hide_members_shelf_summary_off">メンバー欄は表示されます</string>
@@ -347,30 +347,30 @@ GmsCore の電池の最適化を無効にしても、バッテリーの使用に
<string name="revanced_hide_comments_timestamp_button_title">タイムスタンプ ボタンを非表示</string> <string name="revanced_hide_comments_timestamp_button_title">タイムスタンプ ボタンを非表示</string>
<string name="revanced_hide_comments_timestamp_button_summary_on">タイムスタンプ ボタンは表示されません</string> <string name="revanced_hide_comments_timestamp_button_summary_on">タイムスタンプ ボタンは表示されません</string>
<string name="revanced_hide_comments_timestamp_button_summary_off">タイムスタンプ ボタンは表示されます</string> <string name="revanced_hide_comments_timestamp_button_summary_off">タイムスタンプ ボタンは表示されます</string>
<string name="revanced_custom_filter_screen_title">カスタムフィルタ</string> <string name="revanced_custom_filter_screen_title">カスタム フィルタ</string>
<string name="revanced_custom_filter_screen_summary">カスタムフィルタを使用してコンポーネントを非表示にします</string> <string name="revanced_custom_filter_screen_summary">カスタム フィルタを使用してコンポーネントを非表示にします</string>
<string name="revanced_custom_filter_title">カスタムフィルタを有効化</string> <string name="revanced_custom_filter_title">カスタム フィルタを有効化</string>
<string name="revanced_custom_filter_summary_on">カスタムフィルタは有効です</string> <string name="revanced_custom_filter_summary_on">カスタム フィルタは有効です</string>
<string name="revanced_custom_filter_summary_off">カスタムフィルタは無効です</string> <string name="revanced_custom_filter_summary_off">カスタム フィルタは無効です</string>
<string name="revanced_custom_filter_strings_title">カスタムフィルタ</string> <string name="revanced_custom_filter_strings_title">カスタム フィルタ</string>
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. --> <!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
<string name="revanced_custom_filter_strings_summary">非表示にしたい component の path builder string を改行区切りで入力します</string> <string name="revanced_custom_filter_strings_summary">非表示にするコンポーネントの path builder string のリスト (改行区切り)</string>
<string name="revanced_custom_filter_toast_invalid_syntax">無効なカスタムフィルタ: %s</string> <string name="revanced_custom_filter_toast_invalid_syntax">無効なカスタム フィルタ: %s</string>
<string name="revanced_hide_keyword_content_screen_title">キーワード フィルタ</string> <string name="revanced_hide_keyword_content_screen_title">キーワードでコンテンツを非表示</string>
<string name="revanced_hide_keyword_content_screen_summary">キーワードフィルタを使用してフィード、検索結果に表示される動画を非表示にします</string> <string name="revanced_hide_keyword_content_screen_summary">キーワード フィルタを使用してフィード、検索結果に表示される動画を非表示にします</string>
<string name="revanced_hide_keyword_content_home_title">ホームの動画をキーワードで非表示</string> <string name="revanced_hide_keyword_content_home_title">ホームの動画をキーワードで非表示</string>
<string name="revanced_hide_keyword_content_home_summary_on">ホームタブの動画はキーワードでフィルタリングされます</string> <string name="revanced_hide_keyword_content_home_summary_on">ホームタブの動画はキーワードでフィルタリングされます</string>
<string name="revanced_hide_keyword_content_home_summary_off">ホームタブの動画はキーワードでフィルタリングされません</string> <string name="revanced_hide_keyword_content_home_summary_off">ホームタブの動画はキーワードでフィルタリングされません</string>
<string name="revanced_hide_keyword_content_search_title">検索結果をキーワードで非表示</string> <string name="revanced_hide_keyword_content_search_title">検索結果をキーワードで非表示</string>
<string name="revanced_hide_keyword_content_search_summary_on">検索結果はキーワードでフィルタリングされます</string> <string name="revanced_hide_keyword_content_search_summary_on">検索結果はキーワードでフィルタリングされます</string>
<string name="revanced_hide_keyword_content_search_summary_off">検索結果はキーワードでフィルタリングされません</string> <string name="revanced_hide_keyword_content_search_summary_off">検索結果はキーワードでフィルタリングされません</string>
<string name="revanced_hide_keyword_content_subscriptions_title">登録チャンネルの動画をキーワードで非表示</string> <string name="revanced_hide_keyword_content_subscriptions_title">登録チャンネルの動画をキーワードで非表示</string>
<string name="revanced_hide_keyword_content_subscriptions_summary_on">登録チャンネルタブの動画はキーワードでフィルタリングされます</string> <string name="revanced_hide_keyword_content_subscriptions_summary_on">登録チャンネルタブの動画はキーワードでフィルタリングされます</string>
<string name="revanced_hide_keyword_content_subscriptions_summary_off">登録チャンネルタブの動画はキーワードでフィルタリングされません</string> <string name="revanced_hide_keyword_content_subscriptions_summary_off">登録チャンネルタブの動画はキーワードでフィルタリングされません</string>
<string name="revanced_hide_keyword_content_phrases_title">キーワード</string> <string name="revanced_hide_keyword_content_phrases_title">キーワード</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. <!-- 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. --> 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">"キーワードとなる単語やフレーズを改行区切りで入力します <string name="revanced_hide_keyword_content_phrases_summary">"キーワードとなる単語やフレーズのリスト (改行区切り)
動画のタイトルまたはチャンネル名にキーワードが含まれる動画が非表示の対象になります 動画のタイトルまたはチャンネル名にキーワードが含まれる動画が非表示の対象になります
@@ -379,7 +379,7 @@ GmsCore の電池の最適化を無効にしても、バッテリーの使用に
<string name="revanced_hide_keyword_content_about_summary">"ホーム / 登録チャンネル / 検索結果でキーワードに合致する動画を非表示にします <string name="revanced_hide_keyword_content_about_summary">"ホーム / 登録チャンネル / 検索結果でキーワードに合致する動画を非表示にします
制限事項 制限事項
• ショート動画はチャンネル名で除外されない • ショート動画はチャンネル名で非表示にできない
• 一部の UI コンポーネントが残ってしまう場合がある • 一部の UI コンポーネントが残ってしまう場合がある
• キーワードを検索したとき、結果が表示されない場合がある"</string> • キーワードを検索したとき、結果が表示されない場合がある"</string>
<string name="revanced_hide_keyword_content_about_whole_words_title">単語全体で合致</string> <string name="revanced_hide_keyword_content_about_whole_words_title">単語全体で合致</string>
@@ -619,17 +619,17 @@ GmsCore の電池の最適化を無効にしても、バッテリーの使用に
<string name="revanced_hide_notifications_button_summary_off">通知ボタンは表示されます</string> <string name="revanced_hide_notifications_button_summary_off">通知ボタンは表示されます</string>
<!-- 'Notifications' should be translated using the same localized wording YouTube displays the tab. --> <!-- 'Notifications' should be translated using the same localized wording YouTube displays the tab. -->
<string name="revanced_switch_create_with_notifications_button_title">「作成」と「通知」を入れ替え</string> <string name="revanced_switch_create_with_notifications_button_title">「作成」と「通知」を入れ替え</string>
<string name="revanced_switch_create_with_notifications_button_summary_on">"作成ボタンと通知ボタン入れ替ます <string name="revanced_switch_create_with_notifications_button_summary_on">"作成ボタンと通知ボタン入れ替わります
注: これにより、動画広告も強制的に非表示になります"</string> 注: これにより、動画広告も強制的に非表示になります"</string>
<string name="revanced_switch_create_with_notifications_button_summary_off">作成ボタンと通知ボタン入れ替えます\n\n注: これにより、動画広告も強制的に非表示になります</string> <string name="revanced_switch_create_with_notifications_button_summary_off">作成ボタンと通知ボタン入れ替わりません</string>
<string name="revanced_switch_create_with_notifications_button_user_dialog_message">"この設定を無効にすると、ショート動画の広告ブロックも無効になります。 <string name="revanced_switch_create_with_notifications_button_user_dialog_message">"この設定を無効にすると、ショート動画の広告ブロックも無効になります。
この設定を変更しても効果がない場合は、シークレット モードに切り替えてみてください。"</string> この設定を変更しても効果がない場合は、シークレット モードに切り替えてみてください。"</string>
<string name="revanced_hide_navigation_button_labels_title">ボタンをアイコンのみで表示</string> <string name="revanced_hide_navigation_button_labels_title">ボタンをアイコンのみで表示</string>
<string name="revanced_hide_navigation_button_labels_summary_on">ナビゲーション ボタンはアイコンのみで表示されます</string> <string name="revanced_hide_navigation_button_labels_summary_on">ナビゲーション ボタンはアイコンのみで表示されます</string>
<string name="revanced_hide_navigation_button_labels_summary_off">ナビゲーション ボタンはアイコンと文字で表示されます</string> <string name="revanced_hide_navigation_button_labels_summary_off">ナビゲーション ボタンはアイコンと文字で表示されます</string>
<string name="revanced_disable_translucent_status_bar_title">ステータスバーの半透明化を無効にする</string> <string name="revanced_disable_translucent_status_bar_title">ステータスバーの半透明化を無効</string>
<string name="revanced_disable_translucent_status_bar_summary_on">ステータスバーは常に透けません</string> <string name="revanced_disable_translucent_status_bar_summary_on">ステータスバーは常に透けません</string>
<string name="revanced_disable_translucent_status_bar_summary_off">ステータスバーは状況に応じて透けます</string> <string name="revanced_disable_translucent_status_bar_summary_off">ステータスバーは状況に応じて透けます</string>
<string name="revanced_disable_translucent_status_bar_user_dialog_message">一部のデバイスでは、この機能を有効にすると、システムのナビゲーション バーが半透明になりアプリ内のコンポーネントに重なってしまう可能性があります。</string> <string name="revanced_disable_translucent_status_bar_user_dialog_message">一部のデバイスでは、この機能を有効にすると、システムのナビゲーション バーが半透明になりアプリ内のコンポーネントに重なってしまう可能性があります。</string>
@@ -695,6 +695,9 @@ GmsCore の電池の最適化を無効にしても、バッテリーの使用に
<string name="revanced_hide_player_flyout_watch_in_vr_title">「VR で見る」を非表示</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">「VR で見る」を非表示</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">「VR で見る」は表示されません</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">「VR で見る」は表示されません</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">「VR で見る」は表示されます</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">「VR で見る」は表示されます</string>
<string name="revanced_hide_player_flyout_video_quality_title">画質のメニューを非表示にする</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">画質メニューは非表示です</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">画質メニューは表示されます</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">画質設定メニューの脚注を非表示</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">画質設定メニューの脚注を非表示</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">画質設定メニューの脚注は表示されません</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">画質設定メニューの脚注は表示されません</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">画質設定メニューの脚注は表示されます</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">画質設定メニューの脚注は表示されます</string>
@@ -1190,15 +1193,15 @@ Automotive レイアウト
• フィードがトピックやチャンネルごとに分類された形で表示される"</string> • フィードがトピックやチャンネルごとに分類された形で表示される"</string>
</patch> </patch>
<patch id="layout.spoofappversion.spoofAppVersionPatch"> <patch id="layout.spoofappversion.spoofAppVersionPatch">
<string name="revanced_spoof_app_version_title">アプリのバージョンを偽装する</string> <string name="revanced_spoof_app_version_title">アプリのバージョンを偽装</string>
<string name="revanced_spoof_app_version_summary_on">アプリのバージョンは偽装されています</string> <string name="revanced_spoof_app_version_summary_on">アプリのバージョンは偽装されています</string>
<string name="revanced_spoof_app_version_summary_off">アプリのバージョンは偽装されていません</string> <string name="revanced_spoof_app_version_summary_off">アプリのバージョンは偽装されていません</string>
<string name="revanced_spoof_app_version_user_dialog_message">"アプリのバージョンを YouTube の古いバージョンに偽装します。 <string name="revanced_spoof_app_version_user_dialog_message">"アプリのバージョンを YouTube の古いバージョンに偽装します。
アプリの外観と機能が変化しますが、予期せぬ副作用が発生する可能性があります。 アプリの外観と機能が変化しますが、予期せぬ副作用が発生する可能性があります。
再び無効にする場合は、UI のバグを防ぐためにアプリデータを消去することをお勧めします。"</string> 再び偽装を無効にする場合は、UI のバグを防ぐためにアプリデータを消去することをお勧めします。"</string>
<string name="revanced_spoof_app_version_target_title">アプリバージョン</string> <string name="revanced_spoof_app_version_target_title">アプリバージョンの偽装先</string>
<string name="revanced_spoof_app_version_target_entry_1">19.35.36 - 古いショート プレーヤーのアイコンを復元</string> <string name="revanced_spoof_app_version_target_entry_1">19.35.36 - 古いショート プレーヤーのアイコンを復元</string>
<string name="revanced_spoof_app_version_target_entry_2">19.01.34 - 古いナビゲーション アイコンを復元</string> <string name="revanced_spoof_app_version_target_entry_2">19.01.34 - 古いナビゲーション アイコンを復元</string>
</patch> </patch>
@@ -1229,15 +1232,15 @@ Automotive レイアウト
<string name="revanced_change_start_page_entry_watch_later">後で見る</string> <string name="revanced_change_start_page_entry_watch_later">後で見る</string>
<string name="revanced_change_start_page_entry_your_clips">自分のクリップ</string> <string name="revanced_change_start_page_entry_your_clips">自分のクリップ</string>
<string name="revanced_change_start_page_always_title">スタート画面の変更を常時適用</string> <string name="revanced_change_start_page_always_title">スタート画面の変更を常時適用</string>
<string name="revanced_change_start_page_always_summary_on">"スタート画面の変更は常時適用されます <string name="revanced_change_start_page_always_summary_on">"スタート画面の変更は常時適用されます
制限事項: ツールバーの [戻る] ボタンが機能しない可能性があります"</string> 制限事項: ツールバーの [戻る] ボタンが機能しない可能性があります"</string>
<string name="revanced_change_start_page_always_summary_off">スタート画面の変更はアプリ起動時にのみ適用されます</string> <string name="revanced_change_start_page_always_summary_off">スタート画面の変更はアプリ起動時にのみ適用されます</string>
</patch> </patch>
<patch id="layout.startupshortsreset.disableResumingShortsOnStartupPatch"> <patch id="layout.startupshortsreset.disableResumingShortsOnStartupPatch">
<string name="revanced_disable_resuming_shorts_player_title">ショート動画プレーヤーの再開を無効にする</string> <string name="revanced_disable_resuming_shorts_player_title">ショート プレーヤーの再開を無効</string>
<string name="revanced_disable_resuming_shorts_player_summary_on">ショート動画プレーヤーは、アプリ起動時に再開されま</string> <string name="revanced_disable_resuming_shorts_player_summary_on">アプリ起動時にショート プレーヤーは再開されません</string>
<string name="revanced_disable_resuming_shorts_player_summary_off">ショート動画プレーヤーは、アプリの起動時に再開されません</string> <string name="revanced_disable_resuming_shorts_player_summary_off">アプリ起動時にショート プレーヤー再開されま</string>
</patch> </patch>
<patch id="layout.shortsplayer.shortsPlayerTypePatch"> <patch id="layout.shortsplayer.shortsPlayerTypePatch">
<string name="revanced_shorts_player_type_title">ショート動画を開くプレーヤー</string> <string name="revanced_shorts_player_type_title">ショート動画を開くプレーヤー</string>
@@ -1301,7 +1304,7 @@ Automotive レイアウト
<string name="revanced_miniplayer_opacity_invalid_toast">ミニプレーヤー: 透明度の範囲は 0-100 です</string> <string name="revanced_miniplayer_opacity_invalid_toast">ミニプレーヤー: 透明度の範囲は 0-100 です</string>
</patch> </patch>
<patch id="layout.theme.themePatch"> <patch id="layout.theme.themePatch">
<string name="revanced_gradient_loading_screen_title">グラデーションの読み込み画面を使用する</string> <string name="revanced_gradient_loading_screen_title">グラデーションの読み込み画面を有効化</string>
<string name="revanced_gradient_loading_screen_summary_on">画面読み込み時にグラデーションの背景が表示されます</string> <string name="revanced_gradient_loading_screen_summary_on">画面読み込み時にグラデーションの背景が表示されます</string>
<string name="revanced_gradient_loading_screen_summary_off">画面読み込み時に通常の背景が表示されます</string> <string name="revanced_gradient_loading_screen_summary_off">画面読み込み時に通常の背景が表示されます</string>
<string name="revanced_splash_screen_animation_style_title">スプラッシュ画面のスタイル</string> <string name="revanced_splash_screen_animation_style_title">スプラッシュ画面のスタイル</string>
@@ -1348,8 +1351,8 @@ Automotive レイアウト
詳細については、ここをタップしてください"</string> 詳細については、ここをタップしてください"</string>
<string name="revanced_alt_thumbnail_dearrow_connection_toast_title">API 利用不可時にトーストを表示</string> <string name="revanced_alt_thumbnail_dearrow_connection_toast_title">API 利用不可時にトーストを表示</string>
<string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_on">DeArrow が利用できない場合は、トーストポップアップが表示されます</string> <string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_on">DeArrow が利用できない場合トースト通知が表示されます</string>
<string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_off">DeArrow が利用できない場合でも、トースト ポップアップは表示されません</string> <string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_off">DeArrow が利用できない場合トースト通知は表示されません</string>
<string name="revanced_alt_thumbnail_dearrow_api_url_title">DeArrow API のエンドポイント</string> <string name="revanced_alt_thumbnail_dearrow_api_url_title">DeArrow API のエンドポイント</string>
<string name="revanced_alt_thumbnail_dearrow_api_url_summary">DeArrow がサムネイルのキャッシュを取得するエンドポイントの URL</string> <string name="revanced_alt_thumbnail_dearrow_api_url_summary">DeArrow がサムネイルのキャッシュを取得するエンドポイントの URL</string>
<string name="revanced_alt_thumbnail_stills_about_title">静止画サムネイル</string> <string name="revanced_alt_thumbnail_stills_about_title">静止画サムネイル</string>
@@ -1465,7 +1468,7 @@ Automotive レイアウト
<string name="revanced_playback_speed_dialog_button_summary_on">ボタンがオーバーレイに表示されます。長押しすると、再生速度がデフォルトの値にリセットされます</string> <string name="revanced_playback_speed_dialog_button_summary_on">ボタンがオーバーレイに表示されます。長押しすると、再生速度がデフォルトの値にリセットされます</string>
<string name="revanced_playback_speed_dialog_button_summary_off">ボタンはオーバーレイに表示されません</string> <string name="revanced_playback_speed_dialog_button_summary_off">ボタンはオーバーレイに表示されません</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">画質設定ボタンを表示</string> <string name="revanced_video_quality_dialog_button_title">画質設定ボタンを表示</string>
<string name="revanced_video_quality_dialog_button_summary_on">ボタンがオーバーレイに表示されます。長押しすると、画質がデフォルトの値にリセットされます</string> <string name="revanced_video_quality_dialog_button_summary_on">ボタンがオーバーレイに表示されます。長押しすると、画質がデフォルトの値にリセットされます</string>
<string name="revanced_video_quality_dialog_button_summary_off">ボタンはオーバーレイに表示されません</string> <string name="revanced_video_quality_dialog_button_summary_off">ボタンはオーバーレイに表示されません</string>
@@ -1502,7 +1505,7 @@ Automotive レイアウト
</patch> </patch>
<patch id="video.quality.advancedVideoQualityMenuPatch"> <patch id="video.quality.advancedVideoQualityMenuPatch">
<string name="revanced_advanced_video_quality_menu_title">画質の詳細設定メニューを表示</string> <string name="revanced_advanced_video_quality_menu_title">画質の詳細設定メニューを表示</string>
<string name="revanced_advanced_video_quality_menu_summary_on">画質メニューとして詳細設定メニューが表示されます</string> <string name="revanced_advanced_video_quality_menu_summary_on">詳細設定メニューが画質メニューとして表示されます</string>
<string name="revanced_advanced_video_quality_menu_summary_off">通常の画質メニューが表示されます</string> <string name="revanced_advanced_video_quality_menu_summary_off">通常の画質メニューが表示されます</string>
</patch> </patch>
<patch id="interaction.seekbar.enableSlideToSeekPatch"> <patch id="interaction.seekbar.enableSlideToSeekPatch">

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -237,7 +237,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -692,6 +692,9 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배
<string name="revanced_hide_player_flyout_watch_in_vr_title">VR로 보기 메뉴 숨기기</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">VR로 보기 메뉴 숨기기</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">VR로 보기 메뉴가 숨겨집니다</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">VR로 보기 메뉴가 숨겨집니다</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">VR로 보기 메뉴가 표시됩니다</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">VR로 보기 메뉴가 표시됩니다</string>
<string name="revanced_hide_player_flyout_video_quality_title">동영상 화질 메뉴 숨기기</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">동영상 화질 메뉴가 숨겨집니다</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">동영상 화질 메뉴가 표시됩니다</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">화질 설정 메뉴에서 하단 설명 숨기기</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">화질 설정 메뉴에서 하단 설명 숨기기</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">화질 설정 메뉴에서 하단 설명이 숨겨집니다</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">화질 설정 메뉴에서 하단 설명이 숨겨집니다</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">화질 설정 메뉴에서 하단 설명이 표시됩니다</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">화질 설정 메뉴에서 하단 설명이 표시됩니다</string>
@@ -1472,7 +1475,7 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요"</string>
<string name="revanced_playback_speed_dialog_button_summary_on">버튼을 표시합니다\n\n• 버튼을 길게 누르면 동영상 재생 속도가 기본값으로 초기화됩니다</string> <string name="revanced_playback_speed_dialog_button_summary_on">버튼을 표시합니다\n\n• 버튼을 길게 누르면 동영상 재생 속도가 기본값으로 초기화됩니다</string>
<string name="revanced_playback_speed_dialog_button_summary_off">버튼을 표시하지 않습니다</string> <string name="revanced_playback_speed_dialog_button_summary_off">버튼을 표시하지 않습니다</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">동영상 화질 버튼 표시하기</string> <string name="revanced_video_quality_dialog_button_title">동영상 화질 버튼 표시하기</string>
<string name="revanced_video_quality_dialog_button_summary_on">버튼을 표시합니다\n\n• 버튼을 길게 누르면 화질이 기본값으로 초기화됩니다</string> <string name="revanced_video_quality_dialog_button_summary_on">버튼을 표시합니다\n\n• 버튼을 길게 누르면 화질이 기본값으로 초기화됩니다</string>
<string name="revanced_video_quality_dialog_button_summary_off">버튼을 표시하지 않습니다</string> <string name="revanced_video_quality_dialog_button_summary_off">버튼을 표시하지 않습니다</string>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -691,6 +691,9 @@ Jei pakeitus šį nustatymą neįsigalioja, pabandykite perjungti į inkognito r
<string name="revanced_hide_player_flyout_watch_in_vr_title">Slėpti Žiūrėti VR</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">Slėpti Žiūrėti VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Žiūrėti VR meniu yra paslėptas</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Žiūrėti VR meniu yra paslėptas</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Žiūrėti VR meniu yra rodomas</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Žiūrėti VR meniu yra rodomas</string>
<string name="revanced_hide_player_flyout_video_quality_title">Slėpti vaizdo kokybės meniu</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">Vaizdo kokybės meniu yra paslėptas</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">Vaizdo kokybės meniu yra rodomas</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Slėpti vaizdo kokybės meniu apatinę juostą</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">Slėpti vaizdo kokybės meniu apatinę juostą</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Vaizdo kokybės meniu apatinė juosta yra paslėpta</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Vaizdo kokybės meniu apatinė juosta yra paslėpta</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Vaizdo kokybės meniu apatinė juosta yra rodoma</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Vaizdo kokybės meniu apatinė juosta yra rodoma</string>
@@ -1464,7 +1467,7 @@ Gali būti atrakinta aukštesnės vaizdo įrašų kokybės, bet galite patirti v
<string name="revanced_playback_speed_dialog_button_summary_on">Mygtukas rodomas. Palieskite ir palaikykite, kad atkūrimo greitį nustatytumėte į numatytąjį.</string> <string name="revanced_playback_speed_dialog_button_summary_on">Mygtukas rodomas. Palieskite ir palaikykite, kad atkūrimo greitį nustatytumėte į numatytąjį.</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Mygtukas nerodomas</string> <string name="revanced_playback_speed_dialog_button_summary_off">Mygtukas nerodomas</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Rodyti vaizdo kokybės mygtuką</string> <string name="revanced_video_quality_dialog_button_title">Rodyti vaizdo kokybės mygtuką</string>
<string name="revanced_video_quality_dialog_button_summary_on">Mygtukas rodomas. Palaikykite nuspaudę, kad atstatytumėte kokybę į numatytąją</string> <string name="revanced_video_quality_dialog_button_summary_on">Mygtukas rodomas. Palaikykite nuspaudę, kad atstatytumėte kokybę į numatytąją</string>
<string name="revanced_video_quality_dialog_button_summary_off">Mygtukas nerodomas</string> <string name="revanced_video_quality_dialog_button_summary_off">Mygtukas nerodomas</string>

View File

@@ -693,6 +693,9 @@ Lai parādītu audio celiņu izvēlni, mainiet \"Video straumju viltošana\" uz
<string name="revanced_hide_player_flyout_watch_in_vr_title">Paslēpt Skatīties VR</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">Paslēpt Skatīties VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Skatīties VR izvēlne ir paslēpta</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Skatīties VR izvēlne ir paslēpta</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Skatīties VR izvēlne ir redzama</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Skatīties VR izvēlne ir redzama</string>
<string name="revanced_hide_player_flyout_video_quality_title">Paslēpt video kvalitātes izvēlni</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">Video kvalitātes izvēlne ir paslēpta</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">Video kvalitātes izvēlne ir redzama</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Paslēpt video kvalitātes izvēlnes apakšējo daļu</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">Paslēpt video kvalitātes izvēlnes apakšējo daļu</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Video kvalitātes izvēlnes apakšējā daļa ir paslēpta</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Video kvalitātes izvēlnes apakšējā daļa ir paslēpta</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Video kvalitātes izvēlnes apakšējā daļa ir redzama</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Video kvalitātes izvēlnes apakšējā daļa ir redzama</string>
@@ -1466,7 +1469,7 @@ Var tikt atbloķētas augstākas video kvalitātes, taču var rasties video atsk
<string name="revanced_playback_speed_dialog_button_summary_on">Poga ir redzama. Pieskarieties un turiet, lai atiestatītu atskaņošanas ātrumu uz noklusējuma</string> <string name="revanced_playback_speed_dialog_button_summary_on">Poga ir redzama. Pieskarieties un turiet, lai atiestatītu atskaņošanas ātrumu uz noklusējuma</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Poga netiek rādīta</string> <string name="revanced_playback_speed_dialog_button_summary_off">Poga netiek rādīta</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Rādīt video kvalitātes pogu</string> <string name="revanced_video_quality_dialog_button_title">Rādīt video kvalitātes pogu</string>
<string name="revanced_video_quality_dialog_button_summary_on">Poga tiek rādīta. Pieskarieties un turiet, lai atiestatītu kvalitāti uz noklusējuma</string> <string name="revanced_video_quality_dialog_button_summary_on">Poga tiek rādīta. Pieskarieties un turiet, lai atiestatītu kvalitāti uz noklusējuma</string>
<string name="revanced_video_quality_dialog_button_summary_off">Poga netiek rādīta</string> <string name="revanced_video_quality_dialog_button_summary_off">Poga netiek rādīta</string>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -223,7 +223,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -21,6 +21,8 @@ Second \"item\" text"</string>
<resources> <resources>
<app id="shared"> <app id="shared">
<patch id="misc.checks.checkEnvironmentPatch"> <patch id="misc.checks.checkEnvironmentPatch">
<string name="revanced_check_environment_manager_not_expected_installer">ReVanced Manager द्वारा स्थापित छैन</string>
<string name="revanced_check_environment_not_near_patch_time_invalid">APK निर्माण मिति खराब भएको छ</string>
</patch> </patch>
<patch id="misc.settings.settingsResourcePatch"> <patch id="misc.settings.settingsResourcePatch">
<!-- Settings about dialog. --> <!-- Settings about dialog. -->
@@ -222,7 +224,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -693,6 +693,9 @@ Om het audiotrackmenu weer te geven, wijzigt u 'Videostreams vervalsen' in iOS T
<string name="revanced_hide_player_flyout_watch_in_vr_title">Verberg Bekijk in VR</string> <string name="revanced_hide_player_flyout_watch_in_vr_title">Verberg Bekijk in VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Menu Bekijk in VR is verborgen</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Menu Bekijk in VR is verborgen</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Menu Bekijk in VR wordt weergegeven</string> <string name="revanced_hide_player_flyout_watch_in_vr_summary_off">Menu Bekijk in VR wordt weergegeven</string>
<string name="revanced_hide_player_flyout_video_quality_title">Videokwaliteitsmenu verbergen</string>
<string name="revanced_hide_player_flyout_video_quality_summary_on">Videokwaliteitsmenu is verborgen</string>
<string name="revanced_hide_player_flyout_video_quality_summary_off">Videokwaliteitsmenu is zichtbaar</string>
<string name="revanced_hide_player_flyout_video_quality_footer_title">Verberg voettekst van video-kwaliteitsmenu</string> <string name="revanced_hide_player_flyout_video_quality_footer_title">Verberg voettekst van video-kwaliteitsmenu</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Voettekst van video-kwaliteitsmenu is verborgen</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_on">Voettekst van video-kwaliteitsmenu is verborgen</string>
<string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Voettekst van video-kwaliteitsmenu wordt weergegeven</string> <string name="revanced_hide_player_flyout_video_quality_footer_summary_off">Voettekst van video-kwaliteitsmenu wordt weergegeven</string>
@@ -1463,7 +1466,7 @@ Het inschakelen hiervan kan hogere videokwaliteiten ontgrendelen"</string>
<string name="revanced_playback_speed_dialog_button_summary_on">De knop wordt weergegeven. Tik en houd vast om de afspeelsnelheid terug te zetten naar de standaardwaarde</string> <string name="revanced_playback_speed_dialog_button_summary_on">De knop wordt weergegeven. Tik en houd vast om de afspeelsnelheid terug te zetten naar de standaardwaarde</string>
<string name="revanced_playback_speed_dialog_button_summary_off">Knop wordt niet weergegeven</string> <string name="revanced_playback_speed_dialog_button_summary_off">Knop wordt niet weergegeven</string>
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
<string name="revanced_video_quality_dialog_button_title">Toon videokwaliteitknop</string> <string name="revanced_video_quality_dialog_button_title">Toon videokwaliteitknop</string>
<string name="revanced_video_quality_dialog_button_summary_on">Knop wordt weergegeven. Tik en houd vast om de kwaliteit terug te zetten naar standaard</string> <string name="revanced_video_quality_dialog_button_summary_on">Knop wordt weergegeven. Tik en houd vast om de kwaliteit terug te zetten naar standaard</string>
<string name="revanced_video_quality_dialog_button_summary_off">Knop wordt niet weergegeven</string> <string name="revanced_video_quality_dialog_button_summary_off">Knop wordt niet weergegeven</string>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

View File

@@ -222,7 +222,7 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="video.speed.button.playbackSpeedButtonPatch"> <patch id="video.speed.button.playbackSpeedButtonPatch">
</patch> </patch>
<patch id="video.quality.button.videoQualityButtonPatch"> <patch id="video.quality.button.videoQualityDialogButtonPatch">
</patch> </patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch"> <patch id="video.speed.custom.customPlaybackSpeedPatch">
</patch> </patch>

Some files were not shown because too many files have changed in this diff Show More