mirror of
https://github.com/ReVanced/revanced-patches.git
synced 2026-01-13 06:27:41 +00:00
Compare commits
57 Commits
v5.31.2-de
...
v5.33.0-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c31374c53 | ||
|
|
2e177a8839 | ||
|
|
cfffd422f8 | ||
|
|
37aab8382e | ||
|
|
f4950ec2ea | ||
|
|
7bdc32867a | ||
|
|
6e60ac6963 | ||
|
|
1adbd563b2 | ||
|
|
9ccf13b680 | ||
|
|
7b8ca9c018 | ||
|
|
ae6dd23d08 | ||
|
|
b1d164b446 | ||
|
|
87c39dd485 | ||
|
|
1549ac12aa | ||
|
|
5d08fdddb8 | ||
|
|
98114e5bde | ||
|
|
a4817dfdd0 | ||
|
|
d4f05351e1 | ||
|
|
d92362b0d9 | ||
|
|
afc7c75df1 | ||
|
|
f0d4e9bfb4 | ||
|
|
e9e4cf39b6 | ||
|
|
0579a9f760 | ||
|
|
1c0acef3f3 | ||
|
|
2419adb77b | ||
|
|
9e4113555b | ||
|
|
125855540b | ||
|
|
a8eee825e6 | ||
|
|
63859f0ef9 | ||
|
|
1c9000dbda | ||
|
|
8ec857a175 | ||
|
|
f56c7868f5 | ||
|
|
cfd77800d6 | ||
|
|
707deaef0b | ||
|
|
9ddb3ac39d | ||
|
|
a7d3b7c287 | ||
|
|
30bac0397e | ||
|
|
c5fc187a35 | ||
|
|
f46dbcd084 | ||
|
|
2136573cb6 | ||
|
|
86ec08993c | ||
|
|
44da5a71c5 | ||
|
|
e4e81b89ea | ||
|
|
165df659a1 | ||
|
|
bb87afe0f6 | ||
|
|
ac5fb17937 | ||
|
|
e88356b3c5 | ||
|
|
dead9c2d94 | ||
|
|
ca640b2839 | ||
|
|
c972267cd8 | ||
|
|
d0d2c13d16 | ||
|
|
e7b4ab53cf | ||
|
|
f994264d9c | ||
|
|
eb61c1f5d1 | ||
|
|
e578347277 | ||
|
|
294b2dce2e | ||
|
|
aa37105ea3 |
28
.github/dependabot.yml
vendored
28
.github/dependabot.yml
vendored
@@ -1,26 +1,22 @@
|
||||
version: 2
|
||||
multi-ecosystem-groups:
|
||||
dependency:
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
target-branch: dev
|
||||
labels: [ ]
|
||||
|
||||
updates:
|
||||
- package-ecosystem: github-actions
|
||||
multi-ecosystem-group: "dependency"
|
||||
labels: []
|
||||
directory: /
|
||||
patterns:
|
||||
- "*"
|
||||
target-branch: dev
|
||||
schedule:
|
||||
interval: monthly
|
||||
|
||||
- package-ecosystem: npm
|
||||
multi-ecosystem-group: "dependency"
|
||||
labels: []
|
||||
directory: /
|
||||
patterns:
|
||||
- "*"
|
||||
target-branch: dev
|
||||
schedule:
|
||||
interval: monthly
|
||||
|
||||
- package-ecosystem: gradle
|
||||
multi-ecosystem-group: "dependency"
|
||||
labels: []
|
||||
directory: /
|
||||
patterns:
|
||||
- "*"
|
||||
target-branch: dev
|
||||
schedule:
|
||||
interval: monthly
|
||||
|
||||
146
CHANGELOG.md
146
CHANGELOG.md
@@ -1,3 +1,149 @@
|
||||
# [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)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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))
|
||||
|
||||
# [5.33.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.6...v5.33.0-dev.7) (2025-08-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **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))
|
||||
|
||||
# [5.33.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.5...v5.33.0-dev.6) (2025-07-31)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **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))
|
||||
|
||||
# [5.33.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.4...v5.33.0-dev.5) (2025-07-31)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Litho filter:** Correctly filter identifier of older YouTube targets ([bf29d69](https://github.com/ReVanced/revanced-patches/commit/bf29d6909e389819bad878ad3b94bbc90d823cc9))
|
||||
|
||||
# [5.33.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.3...v5.33.0-dev.4) (2025-07-30)
|
||||
|
||||
|
||||
### 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.3](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.2...v5.33.0-dev.3) (2025-07-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Playback speed:** Use old speed menu for player button if enabled ([1e8f436](https://github.com/ReVanced/revanced-patches/commit/1e8f4368e117f4b278c24709231cb32546e46dc0))
|
||||
|
||||
# [5.33.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.33.0-dev.1...v5.33.0-dev.2) (2025-07-29)
|
||||
|
||||
|
||||
### 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))
|
||||
|
||||
# [5.33.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.32.0...v5.33.0-dev.1) (2025-07-28)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **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))
|
||||
|
||||
# [5.32.0](https://github.com/ReVanced/revanced-patches/compare/v5.31.2...v5.32.0) (2025-07-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Messenger - Hide inbox ads:** Support the latest app version ([2959c02](https://github.com/ReVanced/revanced-patches/commit/2959c0214dfa703ee623ef1f89bded7f78c9d252))
|
||||
* **YouTube - Hide layout components:** Fix "Hide ticket shelf" ([#5516](https://github.com/ReVanced/revanced-patches/issues/5516)) ([3b85c71](https://github.com/ReVanced/revanced-patches/commit/3b85c71433325fff49e01c77c7b9ff8ddd0a7068))
|
||||
* **YouTube - GmsCore support:** Fix search suggestions when logged out by using correct search provider ([#5483](https://github.com/ReVanced/revanced-patches/issues/5483)) ([e86fdc8](https://github.com/ReVanced/revanced-patches/commit/e86fdc86b161a6077960b85149e83bacbac664e7))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Prime Video:** Add `Playback speed` patch ([#5444](https://github.com/ReVanced/revanced-patches/issues/5444)) ([22cf313](https://github.com/ReVanced/revanced-patches/commit/22cf313a7b99b69e17b9d488c514802043a5dc10))
|
||||
* **YouTube - External downloads:** Improve the selection of the external downloader package ([#5504](https://github.com/ReVanced/revanced-patches/issues/5504)) ([5de9aa9](https://github.com/ReVanced/revanced-patches/commit/5de9aa9fad4f24186da045fb188f8718d6f63d7a))
|
||||
* **YT Music:** Support latest versions ([#5524](https://github.com/ReVanced/revanced-patches/issues/5524)) ([551dcf0](https://github.com/ReVanced/revanced-patches/commit/551dcf01ca9c489a779196b49c8744727d79d6bc))
|
||||
|
||||
# [5.32.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.32.0-dev.4...v5.32.0-dev.5) (2025-07-26)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YT Music:** Support latest versions ([#5524](https://github.com/ReVanced/revanced-patches/issues/5524)) ([551dcf0](https://github.com/ReVanced/revanced-patches/commit/551dcf01ca9c489a779196b49c8744727d79d6bc))
|
||||
|
||||
# [5.32.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.32.0-dev.3...v5.32.0-dev.4) (2025-07-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Messenger - Hide inbox ads:** Support the latest app version ([2959c02](https://github.com/ReVanced/revanced-patches/commit/2959c0214dfa703ee623ef1f89bded7f78c9d252))
|
||||
|
||||
# [5.32.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.32.0-dev.2...v5.32.0-dev.3) (2025-07-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - External downloads:** Improve the selection of the external downloader package ([#5504](https://github.com/ReVanced/revanced-patches/issues/5504)) ([5de9aa9](https://github.com/ReVanced/revanced-patches/commit/5de9aa9fad4f24186da045fb188f8718d6f63d7a))
|
||||
|
||||
# [5.32.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.32.0-dev.1...v5.32.0-dev.2) (2025-07-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide layout components:** Fix "Hide ticket shelf" ([#5516](https://github.com/ReVanced/revanced-patches/issues/5516)) ([3b85c71](https://github.com/ReVanced/revanced-patches/commit/3b85c71433325fff49e01c77c7b9ff8ddd0a7068))
|
||||
|
||||
# [5.32.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.31.3-dev.1...v5.32.0-dev.1) (2025-07-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Prime Video:** Add `Playback speed` patch ([#5444](https://github.com/ReVanced/revanced-patches/issues/5444)) ([22cf313](https://github.com/ReVanced/revanced-patches/commit/22cf313a7b99b69e17b9d488c514802043a5dc10))
|
||||
|
||||
## [5.31.3-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.31.2...v5.31.3-dev.1) (2025-07-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - GmsCore support:** Fix search suggestions when logged out by using correct search provider ([#5483](https://github.com/ReVanced/revanced-patches/issues/5483)) ([e86fdc8](https://github.com/ReVanced/revanced-patches/commit/e86fdc86b161a6077960b85149e83bacbac664e7))
|
||||
|
||||
## [5.31.2](https://github.com/ReVanced/revanced-patches/compare/v5.31.1...v5.31.2) (2025-07-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Spotify - Spoof client:** Fix login failing by spoofing login request in addition ([#5448](https://github.com/ReVanced/revanced-patches/issues/5448)) ([4e59ddc](https://github.com/ReVanced/revanced-patches/commit/4e59ddc62388d09f71b89593fc8b76933d9facea))
|
||||
* **YouTube - Disable double tap actions:** Remove old incompatible targets ([857053e](https://github.com/ReVanced/revanced-patches/commit/857053e29b72ded10a84b0ac693fa107705342d9))
|
||||
* **YouTube - Hide layout components:** Hide quick actions does not work ([#5423](https://github.com/ReVanced/revanced-patches/issues/5423)) ([9c66729](https://github.com/ReVanced/revanced-patches/commit/9c6672946d44001e106bdac9041e2d79ef3f6ab2))
|
||||
* **YouTube - Hide layout components:** Show correct custom header logo if 'Hide YouTube Doodles' is enabled ([#5431](https://github.com/ReVanced/revanced-patches/issues/5431)) ([20cc141](https://github.com/ReVanced/revanced-patches/commit/20cc141e61f75de1a1749247c4f4aed167dee8ea))
|
||||
* **YouTube - Settings:** Back button/gesture closes search instead of exiting ([#5418](https://github.com/ReVanced/revanced-patches/issues/5418)) ([134b278](https://github.com/ReVanced/revanced-patches/commit/134b278baa7b90d2c4b06200cabacabf55ebc055))
|
||||
|
||||
## [5.31.2-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.31.2-dev.4...v5.31.2-dev.5) (2025-07-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Spotify - Spoof client:** Fix login failing by spoofing login request in addition ([#5448](https://github.com/ReVanced/revanced-patches/issues/5448)) ([4e59ddc](https://github.com/ReVanced/revanced-patches/commit/4e59ddc62388d09f71b89593fc8b76933d9facea))
|
||||
|
||||
## [5.31.2-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.31.2-dev.3...v5.31.2-dev.4) (2025-07-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Settings:** Back button/gesture closes search instead of exiting ([#5418](https://github.com/ReVanced/revanced-patches/issues/5418)) ([134b278](https://github.com/ReVanced/revanced-patches/commit/134b278baa7b90d2c4b06200cabacabf55ebc055))
|
||||
|
||||
## [5.31.2-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.31.2-dev.2...v5.31.2-dev.3) (2025-07-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Disable double tap actions:** Remove old incompatible targets ([857053e](https://github.com/ReVanced/revanced-patches/commit/857053e29b72ded10a84b0ac693fa107705342d9))
|
||||
|
||||
## [5.31.2-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.31.2-dev.1...v5.31.2-dev.2) (2025-07-12)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
package app.revanced.extension.primevideo.videoplayer;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.graphics.RectF;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.PixelFormat;
|
||||
import java.util.Arrays;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
|
||||
import com.amazon.video.sdk.player.Player;
|
||||
|
||||
public class PlaybackSpeedPatch {
|
||||
private static Player player;
|
||||
private static final float[] SPEED_VALUES = {0.5f, 0.7f, 0.8f, 0.9f, 0.95f, 1.0f, 1.05f, 1.1f, 1.2f, 1.3f, 1.5f, 2.0f};
|
||||
private static final String SPEED_BUTTON_TAG = "speed_overlay";
|
||||
|
||||
public static void setPlayer(Player playerInstance) {
|
||||
player = playerInstance;
|
||||
if (player != null) {
|
||||
// Reset playback rate when switching between episodes to ensure correct display.
|
||||
player.setPlaybackRate(1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
public static void initializeSpeedOverlay(View userControlsView) {
|
||||
try {
|
||||
LinearLayout buttonContainer = Utils.getChildViewByResourceName(userControlsView, "ButtonContainerPlayerTop");
|
||||
|
||||
// If the speed overlay exists we should return early.
|
||||
if (Utils.getChildView(buttonContainer, false, child ->
|
||||
child instanceof ImageView && SPEED_BUTTON_TAG.equals(child.getTag())) != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImageView speedButton = createSpeedButton(userControlsView.getContext());
|
||||
speedButton.setOnClickListener(v -> changePlaybackSpeed(speedButton));
|
||||
buttonContainer.addView(speedButton, 0);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
Logger.printException(() -> "initializeSpeedOverlay, no button container found", e);
|
||||
} catch (Exception e) {
|
||||
Logger.printException(() -> "initializeSpeedOverlay failure", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static ImageView createSpeedButton(Context context) {
|
||||
ImageView speedButton = new ImageView(context);
|
||||
speedButton.setContentDescription("Playback Speed");
|
||||
speedButton.setTag(SPEED_BUTTON_TAG);
|
||||
speedButton.setClickable(true);
|
||||
speedButton.setFocusable(true);
|
||||
speedButton.setScaleType(ImageView.ScaleType.CENTER);
|
||||
|
||||
SpeedIconDrawable speedIcon = new SpeedIconDrawable();
|
||||
speedButton.setImageDrawable(speedIcon);
|
||||
|
||||
int buttonSize = Utils.dipToPixels(48);
|
||||
speedButton.setMinimumWidth(buttonSize);
|
||||
speedButton.setMinimumHeight(buttonSize);
|
||||
|
||||
return speedButton;
|
||||
}
|
||||
|
||||
private static String[] getSpeedOptions() {
|
||||
String[] options = new String[SPEED_VALUES.length];
|
||||
for (int i = 0; i < SPEED_VALUES.length; i++) {
|
||||
options[i] = SPEED_VALUES[i] + "x";
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
private static void changePlaybackSpeed(ImageView imageView) {
|
||||
if (player == null) {
|
||||
Logger.printException(() -> "Player not available");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
player.pause();
|
||||
AlertDialog dialog = createSpeedPlaybackDialog(imageView);
|
||||
dialog.setOnDismissListener(dialogInterface -> player.play());
|
||||
dialog.show();
|
||||
|
||||
} catch (Exception e) {
|
||||
Logger.printException(() -> "changePlaybackSpeed", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static AlertDialog createSpeedPlaybackDialog(ImageView imageView) {
|
||||
Context context = imageView.getContext();
|
||||
int currentSelection = getCurrentSpeedSelection();
|
||||
|
||||
return new AlertDialog.Builder(context)
|
||||
.setTitle("Select Playback Speed")
|
||||
.setSingleChoiceItems(getSpeedOptions(), currentSelection,
|
||||
PlaybackSpeedPatch::handleSpeedSelection)
|
||||
.create();
|
||||
}
|
||||
|
||||
private static int getCurrentSpeedSelection() {
|
||||
try {
|
||||
float currentRate = player.getPlaybackRate();
|
||||
int index = Arrays.binarySearch(SPEED_VALUES, currentRate);
|
||||
return Math.max(index, 0); // Use slowest speed if not found.
|
||||
} catch (Exception e) {
|
||||
Logger.printException(() -> "getCurrentSpeedSelection error getting current playback speed", e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static void handleSpeedSelection(android.content.DialogInterface dialog, int selectedIndex) {
|
||||
try {
|
||||
float selectedSpeed = SPEED_VALUES[selectedIndex];
|
||||
player.setPlaybackRate(selectedSpeed);
|
||||
player.play();
|
||||
} catch (Exception e) {
|
||||
Logger.printException(() -> "handleSpeedSelection error setting playback speed", e);
|
||||
} finally {
|
||||
dialog.dismiss();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SpeedIconDrawable extends Drawable {
|
||||
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
int w = getBounds().width();
|
||||
int h = getBounds().height();
|
||||
float centerX = w / 2f;
|
||||
// Position gauge in lower portion.
|
||||
float centerY = h * 0.7f;
|
||||
float radius = Math.min(w, h) / 2f * 0.8f;
|
||||
|
||||
paint.setColor(Color.WHITE);
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(radius * 0.1f);
|
||||
|
||||
// Draw semicircle.
|
||||
RectF oval = new RectF(centerX - radius, centerY - radius, centerX + radius, centerY + radius);
|
||||
canvas.drawArc(oval, 180, 180, false, paint);
|
||||
|
||||
// Draw three tick marks.
|
||||
paint.setStrokeWidth(radius * 0.06f);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
float angle = 180 + (i * 45); // 180°, 225°, 270°.
|
||||
float angleRad = (float) Math.toRadians(angle);
|
||||
|
||||
float startX = centerX + (radius * 0.8f) * (float) Math.cos(angleRad);
|
||||
float startY = centerY + (radius * 0.8f) * (float) Math.sin(angleRad);
|
||||
float endX = centerX + radius * (float) Math.cos(angleRad);
|
||||
float endY = centerY + radius * (float) Math.sin(angleRad);
|
||||
|
||||
canvas.drawLine(startX, startY, endX, endY, paint);
|
||||
}
|
||||
|
||||
// Draw needle.
|
||||
paint.setStrokeWidth(radius * 0.08f);
|
||||
float needleAngle = 200; // Slightly right of center.
|
||||
float needleAngleRad = (float) Math.toRadians(needleAngle);
|
||||
|
||||
float needleEndX = centerX + (radius * 0.6f) * (float) Math.cos(needleAngleRad);
|
||||
float needleEndY = centerY + (radius * 0.6f) * (float) Math.sin(needleAngleRad);
|
||||
|
||||
canvas.drawLine(centerX, centerY, needleEndX, needleEndY, paint);
|
||||
|
||||
// Center dot.
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
canvas.drawCircle(centerX, centerY, radius * 0.06f, paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
paint.setAlpha(alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter colorFilter) {
|
||||
paint.setColorFilter(colorFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.TRANSLUCENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return Utils.dipToPixels(32);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return Utils.dipToPixels(32);
|
||||
}
|
||||
}
|
||||
@@ -4,4 +4,10 @@ public interface VideoPlayer {
|
||||
long getCurrentPosition();
|
||||
|
||||
void seekTo(long positionMs);
|
||||
|
||||
void pause();
|
||||
|
||||
void play();
|
||||
|
||||
boolean isPlaying();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.amazon.video.sdk.player;
|
||||
|
||||
public interface Player {
|
||||
float getPlaybackRate();
|
||||
|
||||
void setPlaybackRate(float rate);
|
||||
|
||||
void play();
|
||||
|
||||
void pause();
|
||||
}
|
||||
@@ -1438,6 +1438,38 @@ public class Utils {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a percentage of the screen height to actual device pixels.
|
||||
*
|
||||
* @param percentage The percentage of the screen height (e.g., 30 for 30%).
|
||||
* @return The device pixel value corresponding to the percentage of screen height.
|
||||
*/
|
||||
public static int percentageHeightToPixels(int percentage) {
|
||||
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
||||
return (int) (metrics.heightPixels * (percentage / 100.0f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a percentage of the screen width to actual device pixels.
|
||||
*
|
||||
* @param percentage The percentage of the screen width (e.g., 30 for 30%).
|
||||
* @return The device pixel value corresponding to the percentage of screen width.
|
||||
*/
|
||||
public static int percentageWidthToPixels(int percentage) {
|
||||
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
||||
return (int) (metrics.widthPixels * (percentage / 100.0f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses {@link #adjustColorBrightness(int, float)} depending if light or dark mode is active.
|
||||
*/
|
||||
@ColorInt
|
||||
public static int adjustColorBrightness(@ColorInt int baseColor, float lightThemeFactor, float darkThemeFactor) {
|
||||
return isDarkModeEnabled()
|
||||
? adjustColorBrightness(baseColor, darkThemeFactor)
|
||||
: adjustColorBrightness(baseColor, lightThemeFactor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the brightness of a color by lightening or darkening it based on the given factor.
|
||||
* <p>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package app.revanced.extension.shared.settings.preference;
|
||||
|
||||
import static app.revanced.extension.shared.Utils.dipToPixels;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
@@ -26,7 +24,7 @@ public class CustomDialogListPreference extends ListPreference {
|
||||
/**
|
||||
* Custom ArrayAdapter to handle checkmark visibility.
|
||||
*/
|
||||
private static class ListPreferenceArrayAdapter extends ArrayAdapter<CharSequence> {
|
||||
public static class ListPreferenceArrayAdapter extends ArrayAdapter<CharSequence> {
|
||||
private static class SubViewDataContainer {
|
||||
ImageView checkIcon;
|
||||
View placeholder;
|
||||
|
||||
@@ -1,28 +1,15 @@
|
||||
package app.revanced.extension.shared.settings.preference;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
import static app.revanced.extension.shared.Utils.dipToPixels;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.graphics.drawable.shapes.RectShape;
|
||||
import android.graphics.drawable.shapes.RoundRectShape;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.os.Bundle;
|
||||
import android.preference.EditTextPreference;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Pair;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package app.revanced.extension.youtube.patches;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class DisableChapterSkipDoubleTapPatch {
|
||||
public final class DisableDoubleTapActionsPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
@@ -1,17 +1,15 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import static app.revanced.extension.youtube.settings.preference.ExternalDownloaderPreference.showDialogIfAppIsNotInstalled;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.StringRef;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@@ -36,7 +34,7 @@ public final class DownloadsPatch {
|
||||
*
|
||||
* Appears to always be called from the main thread.
|
||||
*/
|
||||
public static boolean inAppDownloadButtonOnClick(@NonNull String videoId) {
|
||||
public static boolean inAppDownloadButtonOnClick(String videoId) {
|
||||
try {
|
||||
if (!Settings.EXTERNAL_DOWNLOADER_ACTION_BUTTON.get()) {
|
||||
return false;
|
||||
@@ -48,6 +46,9 @@ public final class DownloadsPatch {
|
||||
boolean isActivityContext = true;
|
||||
if (context == null) {
|
||||
// Utils context is the application context, and not an activity context.
|
||||
//
|
||||
// Edit: This check may no longer be needed since YT can now
|
||||
// only be launched from the main Activity (embedded usage in other apps no longer works).
|
||||
context = Utils.getContext();
|
||||
isActivityContext = false;
|
||||
}
|
||||
@@ -64,8 +65,7 @@ public final class DownloadsPatch {
|
||||
* @param isActivityContext If the context parameter is for an Activity. If this is false, then
|
||||
* the downloader is opened as a new task (which forces YT to minimize).
|
||||
*/
|
||||
public static void launchExternalDownloader(@NonNull String videoId,
|
||||
@NonNull Context context, boolean isActivityContext) {
|
||||
public static void launchExternalDownloader(String videoId, Context context, boolean isActivityContext) {
|
||||
try {
|
||||
Objects.requireNonNull(videoId);
|
||||
Logger.printDebug(() -> "Launching external downloader with context: " + context);
|
||||
@@ -73,16 +73,8 @@ public final class DownloadsPatch {
|
||||
// Trim string to avoid any accidental whitespace.
|
||||
var downloaderPackageName = Settings.EXTERNAL_DOWNLOADER_PACKAGE_NAME.get().trim();
|
||||
|
||||
boolean packageEnabled = false;
|
||||
try {
|
||||
packageEnabled = context.getPackageManager().getApplicationInfo(downloaderPackageName, 0).enabled;
|
||||
} catch (PackageManager.NameNotFoundException error) {
|
||||
Logger.printDebug(() -> "External downloader could not be found: " + error);
|
||||
}
|
||||
|
||||
// If the package is not installed, show the toast
|
||||
if (!packageEnabled) {
|
||||
Utils.showToastLong(StringRef.str("revanced_external_downloader_not_installed_warning", downloaderPackageName));
|
||||
// If the package is not installed, show a dialog.
|
||||
if (showDialogIfAppIsNotInstalled(context, downloaderPackageName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.Objects;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.patches.components.ReturnYouTubeDislikeFilterPatch;
|
||||
import app.revanced.extension.youtube.patches.components.ReturnYouTubeDislikeFilter;
|
||||
import app.revanced.extension.youtube.returnyoutubedislike.ReturnYouTubeDislike;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
@@ -55,7 +55,7 @@ public class ReturnYouTubeDislikePatch {
|
||||
private static volatile ReturnYouTubeDislike lastLithoShortsVideoData;
|
||||
|
||||
/**
|
||||
* Because litho Shorts spans are created offscreen after {@link ReturnYouTubeDislikeFilterPatch}
|
||||
* Because litho Shorts spans are created offscreen after {@link ReturnYouTubeDislikeFilter}
|
||||
* detects the video ids, but the current Short can arbitrarily reload the same span,
|
||||
* then use the {@link #lastLithoShortsVideoData} if this value is greater than zero.
|
||||
*/
|
||||
|
||||
@@ -6,8 +6,6 @@ import android.app.Instrumentation;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
@@ -155,10 +153,10 @@ public final class AdsFilter extends Filter {
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||
boolean isFiltered(String identifier, String path, byte[] buffer,
|
||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||
if (matchedGroup == playerShoppingShelf) {
|
||||
return contentIndex == 0 && playerShoppingShelfBuffer.check(protobufBufferArray).isFiltered();
|
||||
return contentIndex == 0 && playerShoppingShelfBuffer.check(buffer).isFiltered();
|
||||
}
|
||||
|
||||
if (exceptions.matches(path)) {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package app.revanced.extension.youtube.patches.components;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.youtube.patches.playback.quality.AdvancedVideoQualityMenuPatch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@@ -21,7 +19,7 @@ public final class AdvancedVideoQualityMenuFilter extends Filter {
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||
boolean isFiltered(String identifier, String path, byte[] buffer,
|
||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||
isVideoQualityMenuVisible = true;
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package app.revanced.extension.youtube.patches.components;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@@ -100,7 +98,7 @@ final class ButtonsFilter extends Filter {
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||
boolean isFiltered(String identifier, String path, byte[] buffer,
|
||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||
if (matchedGroup == likeSubscribeGlow) {
|
||||
return (path.startsWith(VIDEO_ACTION_BAR_PATH_PREFIX) || path.startsWith(COMPACT_CHANNEL_BAR_PATH_PREFIX))
|
||||
@@ -117,7 +115,7 @@ final class ButtonsFilter extends Filter {
|
||||
// Make sure the current path is the right one
|
||||
// to avoid false positives.
|
||||
return path.startsWith(VIDEO_ACTION_BAR_PATH)
|
||||
&& bufferButtonsGroupList.check(protobufBufferArray).isFiltered();
|
||||
&& bufferButtonsGroupList.check(buffer).isFiltered();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package app.revanced.extension.youtube.patches.components;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
|
||||
@@ -87,12 +85,12 @@ final class CommentsFilter extends Filter {
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||
boolean isFiltered(String identifier, String path, byte[] buffer,
|
||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||
if (matchedGroup == chipBar) {
|
||||
// Playlist sort button uses same components and must only filter if the player is opened.
|
||||
return PlayerType.getCurrent().isMaximizedOrFullscreen()
|
||||
&& aiCommentsSummary.check(protobufBufferArray).isFiltered();
|
||||
&& aiCommentsSummary.check(buffer).isFiltered();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -3,7 +3,6 @@ package app.revanced.extension.youtube.patches.components;
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -146,7 +145,7 @@ final class CustomFilter extends Filter {
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||
boolean isFiltered(String identifier, String path, byte[] buffer,
|
||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||
// All callbacks are custom filter groups.
|
||||
CustomFilterGroup custom = (CustomFilterGroup) matchedGroup;
|
||||
@@ -158,6 +157,6 @@ final class CustomFilter extends Filter {
|
||||
return true; // No buffer filter, only path filtering.
|
||||
}
|
||||
|
||||
return custom.bufferSearch.matches(protobufBufferArray);
|
||||
return custom.bufferSearch.matches(buffer);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package app.revanced.extension.youtube.patches.components;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.youtube.StringTrieSearch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
@@ -105,7 +103,7 @@ final class DescriptionComponentsFilter extends Filter {
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||
boolean isFiltered(String identifier, String path, byte[] buffer,
|
||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||
|
||||
if (matchedGroup == aiGeneratedVideoSummarySection) {
|
||||
@@ -116,11 +114,11 @@ final class DescriptionComponentsFilter extends Filter {
|
||||
if (exceptions.matches(path)) return false;
|
||||
|
||||
if (matchedGroup == macroMarkersCarousel) {
|
||||
return contentIndex == 0 && macroMarkersCarouselGroupList.check(protobufBufferArray).isFiltered();
|
||||
return contentIndex == 0 && macroMarkersCarouselGroupList.check(buffer).isFiltered();
|
||||
}
|
||||
|
||||
if (matchedGroup == horizontalShelf) {
|
||||
return cellVideoAttribute.check(protobufBufferArray).isFiltered();
|
||||
return cellVideoAttribute.check(buffer).isFiltered();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package app.revanced.extension.youtube.patches.components;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -42,6 +40,7 @@ abstract class Filter {
|
||||
/**
|
||||
* Adds callbacks to {@link #isFiltered(String, String, byte[], StringFilterGroup, FilterContentType, int)}
|
||||
* if any of the groups are found.
|
||||
* <p>
|
||||
*/
|
||||
protected final void addIdentifierCallbacks(StringFilterGroup... groups) {
|
||||
identifierCallbacks.addAll(Arrays.asList(groups));
|
||||
@@ -68,7 +67,7 @@ abstract class Filter {
|
||||
* @param contentIndex Matched index of the identifier or path.
|
||||
* @return True if the litho component should be filtered out.
|
||||
*/
|
||||
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||
boolean isFiltered(String identifier, String path, byte[] buffer,
|
||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ package app.revanced.extension.youtube.patches.components;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class HideInfoCardsFilterPatch extends Filter {
|
||||
public final class HideInfoCardsFilter extends Filter {
|
||||
|
||||
public HideInfoCardsFilterPatch() {
|
||||
public HideInfoCardsFilter() {
|
||||
addIdentifierCallbacks(
|
||||
new StringFilterGroup(
|
||||
Settings.HIDE_INFO_CARDS,
|
||||
@@ -554,7 +554,7 @@ final class KeywordContentFilter extends Filter {
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||
boolean isFiltered(String identifier, String path, byte[] buffer,
|
||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||
if (contentIndex != 0 && matchedGroup == startsWithFilter) {
|
||||
return false;
|
||||
@@ -574,7 +574,7 @@ final class KeywordContentFilter extends Filter {
|
||||
}
|
||||
|
||||
MutableReference<String> matchRef = new MutableReference<>();
|
||||
if (bufferSearch.matches(protobufBufferArray, matchRef)) {
|
||||
if (bufferSearch.matches(buffer, matchRef)) {
|
||||
updateStats(true, matchRef.value);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
);
|
||||
|
||||
private final StringTrieSearch exceptions = new StringTrieSearch();
|
||||
private final StringFilterGroup inFeedSurvey;
|
||||
private final StringFilterGroup surveys;
|
||||
private final StringFilterGroup notifyMe;
|
||||
private final StringFilterGroup singleItemInformationPanel;
|
||||
private final StringFilterGroup expandableMetadata;
|
||||
@@ -110,8 +110,8 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
"chip_bar"
|
||||
);
|
||||
|
||||
inFeedSurvey = new StringFilterGroup(
|
||||
Settings.HIDE_FEED_SURVEY,
|
||||
surveys = new StringFilterGroup(
|
||||
Settings.HIDE_SURVEYS,
|
||||
"in_feed_survey",
|
||||
"slimline_survey",
|
||||
"feed_nudge"
|
||||
@@ -266,7 +266,7 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
|
||||
ticketShelf = new ByteArrayFilterGroup(
|
||||
Settings.HIDE_TICKET_SHELF,
|
||||
"ticket.eml"
|
||||
"ticket_item.eml"
|
||||
);
|
||||
|
||||
addPathCallbacks(
|
||||
@@ -286,7 +286,6 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
forYouShelf,
|
||||
horizontalShelves,
|
||||
imageShelf,
|
||||
inFeedSurvey,
|
||||
infoPanel,
|
||||
latestPosts,
|
||||
medicalPanel,
|
||||
@@ -298,13 +297,14 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
singleItemInformationPanel,
|
||||
subscribersCommunityGuidelines,
|
||||
subscriptionsChipBar,
|
||||
surveys,
|
||||
timedReactions,
|
||||
videoRecommendationLabels
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||
boolean isFiltered(String identifier, String path, byte[] buffer,
|
||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||
// This identifier is used not only in players but also in search results:
|
||||
// https://github.com/ReVanced/revanced-patches/issues/3245
|
||||
@@ -317,12 +317,12 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
|
||||
// The groups are excluded from the filter due to the exceptions list below.
|
||||
// Filter them separately here.
|
||||
if (matchedGroup == notifyMe || matchedGroup == inFeedSurvey || matchedGroup == expandableMetadata) {
|
||||
if (matchedGroup == notifyMe || matchedGroup == surveys || matchedGroup == expandableMetadata) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (matchedGroup == channelProfile) {
|
||||
return channelProfileBuffer.check(protobufBufferArray).isFiltered();
|
||||
return channelProfileBuffer.check(buffer).isFiltered();
|
||||
}
|
||||
|
||||
if (exceptions.matches(path)) return false; // Exceptions are not filtered.
|
||||
@@ -331,11 +331,11 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
return compactChannelBarInnerButton.check(path).isFiltered()
|
||||
// The filter may be broad, but in the context of a compactChannelBarInnerButton,
|
||||
// it's safe to assume that the button is the only thing that should be hidden.
|
||||
&& joinMembershipButton.check(protobufBufferArray).isFiltered();
|
||||
&& joinMembershipButton.check(buffer).isFiltered();
|
||||
}
|
||||
|
||||
if (matchedGroup == horizontalShelves) {
|
||||
return contentIndex == 0 && (hideShelves() || ticketShelf.check(protobufBufferArray).isFiltered());
|
||||
return contentIndex == 0 && (hideShelves() || ticketShelf.check(buffer).isFiltered());
|
||||
}
|
||||
|
||||
if (matchedGroup == chipBar) {
|
||||
|
||||
@@ -17,29 +17,28 @@ public final class LithoFilterPatch {
|
||||
* Simple wrapper to pass the litho parameters through the prefix search.
|
||||
*/
|
||||
private static final class LithoFilterParameters {
|
||||
@Nullable
|
||||
final String identifier;
|
||||
final String path;
|
||||
final byte[] protoBuffer;
|
||||
final byte[] buffer;
|
||||
|
||||
LithoFilterParameters(@Nullable String lithoIdentifier, String lithoPath, byte[] protoBuffer) {
|
||||
LithoFilterParameters(String lithoIdentifier, String lithoPath, byte[] buffer) {
|
||||
this.identifier = lithoIdentifier;
|
||||
this.path = lithoPath;
|
||||
this.protoBuffer = protoBuffer;
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
// Estimate the percentage of the buffer that are Strings.
|
||||
StringBuilder builder = new StringBuilder(Math.max(100, protoBuffer.length / 2));
|
||||
StringBuilder builder = new StringBuilder(Math.max(100, buffer.length / 2));
|
||||
builder.append( "ID: ");
|
||||
builder.append(identifier);
|
||||
builder.append(" Path: ");
|
||||
builder.append(path);
|
||||
if (Settings.DEBUG_PROTOBUFFER.get()) {
|
||||
builder.append(" BufferStrings: ");
|
||||
findAsciiStrings(builder, protoBuffer);
|
||||
findAsciiStrings(builder, buffer);
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
@@ -128,21 +127,21 @@ public final class LithoFilterPatch {
|
||||
private static void filterUsingCallbacks(StringTrieSearch pathSearchTree,
|
||||
Filter filter, List<StringFilterGroup> groups,
|
||||
Filter.FilterContentType type) {
|
||||
String filterSimpleName = filter.getClass().getSimpleName();
|
||||
|
||||
for (StringFilterGroup group : groups) {
|
||||
if (!group.includeInSearch()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (String pattern : group.filters) {
|
||||
String filterSimpleName = filter.getClass().getSimpleName();
|
||||
|
||||
pathSearchTree.addPattern(pattern, (textSearched, matchedStartIndex,
|
||||
matchedLength, callbackParameter) -> {
|
||||
if (!group.isEnabled()) return false;
|
||||
|
||||
LithoFilterParameters parameters = (LithoFilterParameters) callbackParameter;
|
||||
final boolean isFiltered = filter.isFiltered(parameters.identifier,
|
||||
parameters.path, parameters.protoBuffer, group, type, matchedStartIndex);
|
||||
parameters.path, parameters.buffer, group, type, matchedStartIndex);
|
||||
|
||||
if (isFiltered && BaseSettings.DEBUG.get()) {
|
||||
if (type == Filter.FilterContentType.IDENTIFIER) {
|
||||
@@ -163,6 +162,7 @@ public final class LithoFilterPatch {
|
||||
|
||||
/**
|
||||
* Injection point. Called off the main thread.
|
||||
* Targets 20.22+
|
||||
*/
|
||||
public static void setProtoBuffer(byte[] buffer) {
|
||||
// Set the buffer to a thread local. The buffer will remain in memory, even after the call to #filter completes.
|
||||
@@ -193,9 +193,9 @@ public final class LithoFilterPatch {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean shouldFilter(@Nullable String lithoIdentifier, StringBuilder pathBuilder) {
|
||||
public static boolean isFiltered(String lithoIdentifier, StringBuilder pathBuilder) {
|
||||
try {
|
||||
if (pathBuilder.length() == 0) {
|
||||
if (lithoIdentifier.isEmpty() && pathBuilder.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ public final class LithoFilterPatch {
|
||||
lithoIdentifier, pathBuilder.toString(), buffer);
|
||||
Logger.printDebug(() -> "Searching " + parameter);
|
||||
|
||||
if (parameter.identifier != null && identifierSearchTree.matches(parameter.identifier, parameter)) {
|
||||
if (identifierSearchTree.matches(parameter.identifier, parameter)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ public final class LithoFilterPatch {
|
||||
return true;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "Litho filter failure", ex);
|
||||
Logger.printException(() -> "isFiltered failure", ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package app.revanced.extension.youtube.patches.components;
|
||||
|
||||
import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
/**
|
||||
* Abuse LithoFilter for {@link CustomPlaybackSpeedPatch}.
|
||||
*/
|
||||
public final class PlaybackSpeedMenuFilter extends Filter {
|
||||
|
||||
/**
|
||||
* Old litho based speed selection menu.
|
||||
*/
|
||||
public static volatile boolean isOldPlaybackSpeedMenuVisible;
|
||||
|
||||
/**
|
||||
* 0.05x speed selection menu.
|
||||
*/
|
||||
public static volatile boolean isPlaybackRateSelectorMenuVisible;
|
||||
|
||||
private final StringFilterGroup oldPlaybackMenuGroup;
|
||||
|
||||
public PlaybackSpeedMenuFilter() {
|
||||
// 0.05x litho speed menu.
|
||||
var playbackRateSelectorGroup = new StringFilterGroup(
|
||||
Settings.CUSTOM_SPEED_MENU,
|
||||
"playback_rate_selector_menu_sheet.eml-js"
|
||||
);
|
||||
|
||||
// Old litho based speed menu.
|
||||
oldPlaybackMenuGroup = new StringFilterGroup(
|
||||
Settings.CUSTOM_SPEED_MENU,
|
||||
"playback_speed_sheet_content.eml-js");
|
||||
|
||||
addPathCallbacks(playbackRateSelectorGroup, oldPlaybackMenuGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isFiltered(String identifier, String path, byte[] buffer,
|
||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||
if (matchedGroup == oldPlaybackMenuGroup) {
|
||||
isOldPlaybackSpeedMenuVisible = true;
|
||||
} else {
|
||||
isPlaybackRateSelectorMenuVisible = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package app.revanced.extension.youtube.patches.components;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
/**
|
||||
* Abuse LithoFilter for {@link CustomPlaybackSpeedPatch}.
|
||||
*/
|
||||
public final class PlaybackSpeedMenuFilterPatch extends Filter {
|
||||
|
||||
/**
|
||||
* 0.05x speed selection menu.
|
||||
*/
|
||||
public static volatile boolean isPlaybackRateSelectorMenuVisible;
|
||||
|
||||
public PlaybackSpeedMenuFilterPatch() {
|
||||
// 0.05x litho speed menu.
|
||||
var playbackRateSelectorGroup = new StringFilterGroup(
|
||||
Settings.CUSTOM_SPEED_MENU,
|
||||
"playback_rate_selector_menu_sheet.eml-js"
|
||||
);
|
||||
|
||||
addPathCallbacks(playbackRateSelectorGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||
isPlaybackRateSelectorMenuVisible = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package app.revanced.extension.youtube.patches.components;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
@@ -96,7 +94,7 @@ public class PlayerFlyoutMenuItemsFilter extends Filter {
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||
boolean isFiltered(String identifier, String path, byte[] buffer,
|
||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||
if (matchedGroup == videoQualityMenuFooter) {
|
||||
return true;
|
||||
@@ -107,10 +105,10 @@ public class PlayerFlyoutMenuItemsFilter extends Filter {
|
||||
}
|
||||
|
||||
// Shorts also use this player flyout panel
|
||||
if (PlayerType.getCurrent().isNoneOrHidden() || exception.check(protobufBufferArray).isFiltered()) {
|
||||
if (PlayerType.getCurrent().isNoneOrHidden() || exception.check(buffer).isFiltered()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return flyoutFilterGroupList.check(protobufBufferArray).isFiltered();
|
||||
return flyoutFilterGroupList.check(buffer).isFiltered();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import app.revanced.extension.youtube.TrieSearch;
|
||||
*
|
||||
* Once a way to asynchronously update litho text is found, this strategy will no longer be needed.
|
||||
*/
|
||||
public final class ReturnYouTubeDislikeFilterPatch extends Filter {
|
||||
public final class ReturnYouTubeDislikeFilter extends Filter {
|
||||
|
||||
/**
|
||||
* Last unique video id's loaded. Value is ignored and Map is treated as a Set.
|
||||
@@ -67,7 +67,7 @@ public final class ReturnYouTubeDislikeFilterPatch extends Filter {
|
||||
|
||||
private final ByteArrayFilterGroupList videoIdFilterGroup = new ByteArrayFilterGroupList();
|
||||
|
||||
public ReturnYouTubeDislikeFilterPatch() {
|
||||
public ReturnYouTubeDislikeFilter() {
|
||||
// When a new Short is opened, the like buttons always seem to load before the dislike.
|
||||
// But if swiping back to a previous video and liking/disliking, then only that single button reloads.
|
||||
// So must check for both buttons.
|
||||
@@ -84,15 +84,15 @@ public final class ReturnYouTubeDislikeFilterPatch extends Filter {
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||
boolean isFiltered(String identifier, String path, byte[] buffer,
|
||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||
if (!Settings.RYD_ENABLED.get() || !Settings.RYD_SHORTS.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FilterGroup.FilterGroupResult result = videoIdFilterGroup.check(protobufBufferArray);
|
||||
FilterGroup.FilterGroupResult result = videoIdFilterGroup.check(buffer);
|
||||
if (result.isFiltered()) {
|
||||
String matchedVideoId = findVideoId(protobufBufferArray);
|
||||
String matchedVideoId = findVideoId(buffer);
|
||||
// Matched video will be null if in incognito mode.
|
||||
// Must pass a null id to correctly clear out the current video data.
|
||||
// Otherwise if a Short is opened in non-incognito, then incognito is enabled and another Short is opened,
|
||||
@@ -4,8 +4,6 @@ import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButt
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.android.libraries.youtube.rendering.ui.pivotbar.PivotBar;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
@@ -13,7 +11,6 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.NavigationBar;
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
@@ -321,7 +318,7 @@ public final class ShortsFilter extends Filter {
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray,
|
||||
boolean isFiltered(String identifier, String path, byte[] buffer,
|
||||
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
|
||||
if (contentType == FilterContentType.PATH) {
|
||||
if (matchedGroup == subscribeButton || matchedGroup == joinButton || matchedGroup == paidPromotionButton) {
|
||||
@@ -330,22 +327,22 @@ public final class ShortsFilter extends Filter {
|
||||
}
|
||||
|
||||
if (matchedGroup == useSoundButton) {
|
||||
return useSoundButtonBuffer.check(protobufBufferArray).isFiltered();
|
||||
return useSoundButtonBuffer.check(buffer).isFiltered();
|
||||
}
|
||||
|
||||
if (matchedGroup == useTemplateButton) {
|
||||
return useTemplateButtonBuffer.check(protobufBufferArray).isFiltered();
|
||||
return useTemplateButtonBuffer.check(buffer).isFiltered();
|
||||
}
|
||||
|
||||
if (matchedGroup == shortsCompactFeedVideo) {
|
||||
return shouldHideShortsFeedItems() && shortsCompactFeedVideoBuffer.check(protobufBufferArray).isFiltered();
|
||||
return shouldHideShortsFeedItems() && shortsCompactFeedVideoBuffer.check(buffer).isFiltered();
|
||||
}
|
||||
|
||||
// Video action buttons (comment, share, remix) have the same path.
|
||||
// Like and dislike are separate path filters and don't require buffer searching.
|
||||
if (matchedGroup == shortsActionBar) {
|
||||
return videoActionButton.check(path).isFiltered()
|
||||
&& videoActionButtonBuffer.check(protobufBufferArray).isFiltered();
|
||||
&& videoActionButtonBuffer.check(buffer).isFiltered();
|
||||
}
|
||||
|
||||
if (matchedGroup == suggestedAction) {
|
||||
@@ -356,7 +353,7 @@ public final class ShortsFilter extends Filter {
|
||||
return true;
|
||||
}
|
||||
|
||||
return suggestedActionsBuffer.check(protobufBufferArray).isFiltered();
|
||||
return suggestedActionsBuffer.check(buffer).isFiltered();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -18,7 +18,7 @@ import app.revanced.extension.youtube.settings.Settings;
|
||||
public final class AdvancedVideoQualityMenuPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* Injection point. Regular videos.
|
||||
*/
|
||||
public static void onFlyoutMenuCreate(RecyclerView recyclerView) {
|
||||
if (!Settings.ADVANCED_VIDEO_QUALITY_MENU.get()) return;
|
||||
@@ -61,22 +61,12 @@ public final class AdvancedVideoQualityMenuPatch {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*
|
||||
* Used to force the creation of the advanced menu item for the Shorts quality flyout.
|
||||
*/
|
||||
public static boolean forceAdvancedVideoQualityMenuCreation(boolean original) {
|
||||
return Settings.ADVANCED_VIDEO_QUALITY_MENU.get() || original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*
|
||||
* Shorts video quality flyout.
|
||||
*/
|
||||
public static void showAdvancedVideoQualityMenu(ListView listView) {
|
||||
public static void addVideoQualityListMenuListener(ListView listView) {
|
||||
if (!Settings.ADVANCED_VIDEO_QUALITY_MENU.get()) return;
|
||||
|
||||
listView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
|
||||
@@ -91,7 +81,6 @@ public final class AdvancedVideoQualityMenuPatch {
|
||||
listView.setSoundEffectsEnabled(false);
|
||||
final var qualityItemMenuPosition = 4;
|
||||
listView.performItemClick(null, qualityItemMenuPosition, 0);
|
||||
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "showAdvancedVideoQualityMenu failure", ex);
|
||||
}
|
||||
@@ -102,4 +91,13 @@ public final class AdvancedVideoQualityMenuPatch {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*
|
||||
* Used to force the creation of the advanced menu item for the Shorts quality flyout.
|
||||
*/
|
||||
public static boolean forceAdvancedVideoQualityMenuCreation(boolean original) {
|
||||
return Settings.ADVANCED_VIDEO_QUALITY_MENU.get() || original;
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,9 @@ import static app.revanced.extension.shared.Utils.NetworkType;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import com.google.android.libraries.youtube.innertube.model.media.VideoQuality;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
@@ -17,10 +17,29 @@ import app.revanced.extension.shared.settings.IntegerSetting;
|
||||
import app.revanced.extension.youtube.patches.VideoInformation;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.ShortsPlayerState;
|
||||
import app.revanced.extension.youtube.videoplayer.VideoQualityDialogButton;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class RememberVideoQualityPatch {
|
||||
private static final int AUTOMATIC_VIDEO_QUALITY_VALUE = -2;
|
||||
|
||||
/**
|
||||
* 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 videoQualityMobile = Settings.VIDEO_QUALITY_DEFAULT_MOBILE;
|
||||
private static final IntegerSetting shortsQualityWifi = Settings.SHORTS_QUALITY_DEFAULT_WIFI;
|
||||
@@ -29,46 +48,83 @@ public class RememberVideoQualityPatch {
|
||||
private static boolean qualityNeedsUpdating;
|
||||
|
||||
/**
|
||||
* If the user selected a new quality from the flyout menu,
|
||||
* and {@link Settings#REMEMBER_VIDEO_QUALITY_LAST_SELECTED} is enabled.
|
||||
*/
|
||||
private static boolean userChangedDefaultQuality;
|
||||
|
||||
/**
|
||||
* Index of the video quality chosen by the user from the flyout menu.
|
||||
*/
|
||||
private static int userSelectedQualityIndex;
|
||||
|
||||
/**
|
||||
* The available qualities of the current video in human readable form: [1080, 720, 480]
|
||||
* The available qualities of the current video.
|
||||
*/
|
||||
@Nullable
|
||||
private static List<Integer> videoQualities;
|
||||
private static List<VideoQuality> currentQualities;
|
||||
|
||||
private static boolean shouldRememberVideoQuality() {
|
||||
BooleanSetting preference = ShortsPlayerState.isOpen() ?
|
||||
Settings.REMEMBER_SHORTS_QUALITY_LAST_SELECTED
|
||||
/**
|
||||
* 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() {
|
||||
BooleanSetting preference = ShortsPlayerState.isOpen()
|
||||
? Settings.REMEMBER_SHORTS_QUALITY_LAST_SELECTED
|
||||
: Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED;
|
||||
return preference.get();
|
||||
}
|
||||
|
||||
private static void changeDefaultQuality(int defaultQuality) {
|
||||
public static int getDefaultQualityResolution() {
|
||||
final boolean isShorts = ShortsPlayerState.isOpen();
|
||||
IntegerSetting preference = Utils.getNetworkType() == NetworkType.MOBILE
|
||||
? (isShorts ? shortsQualityMobile : videoQualityMobile)
|
||||
: (isShorts ? shortsQualityWifi : videoQualityWifi);
|
||||
return preference.get();
|
||||
}
|
||||
|
||||
public static void saveDefaultQuality(int qualityResolution) {
|
||||
final boolean shortPlayerOpen = ShortsPlayerState.isOpen();
|
||||
String networkTypeMessage;
|
||||
boolean useShortsPreference = ShortsPlayerState.isOpen();
|
||||
IntegerSetting qualitySetting;
|
||||
if (Utils.getNetworkType() == NetworkType.MOBILE) {
|
||||
if (useShortsPreference) shortsQualityMobile.save(defaultQuality);
|
||||
else videoQualityMobile.save(defaultQuality);
|
||||
networkTypeMessage = str("revanced_remember_video_quality_mobile");
|
||||
qualitySetting = shortPlayerOpen ? shortsQualityMobile : videoQualityMobile;
|
||||
} else {
|
||||
if (useShortsPreference) shortsQualityWifi.save(defaultQuality);
|
||||
else videoQualityWifi.save(defaultQuality);
|
||||
networkTypeMessage = str("revanced_remember_video_quality_wifi");
|
||||
qualitySetting = shortPlayerOpen ? shortsQualityWifi : videoQualityWifi;
|
||||
}
|
||||
if (Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED_TOAST.get())
|
||||
|
||||
if (qualitySetting.get() == qualityResolution) {
|
||||
// User clicked the same video quality as the current video,
|
||||
// or changed between 1080p Premium and non-Premium.
|
||||
return;
|
||||
}
|
||||
qualitySetting.save(qualityResolution);
|
||||
|
||||
if (Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED_TOAST.get()) {
|
||||
String qualityLabel = qualityResolution + "p";
|
||||
Utils.showToastShort(str(
|
||||
useShortsPreference ? "revanced_remember_video_quality_toast_shorts" : "revanced_remember_video_quality_toast",
|
||||
networkTypeMessage, (defaultQuality + "p")
|
||||
));
|
||||
shortPlayerOpen
|
||||
? "revanced_remember_video_quality_toast_shorts"
|
||||
: "revanced_remember_video_quality_toast",
|
||||
networkTypeMessage,
|
||||
qualityLabel)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,109 +133,131 @@ public class RememberVideoQualityPatch {
|
||||
* @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(Object[] qualities, final int originalQualityIndex, Object qInterface, String qIndexMethod) {
|
||||
public static int setVideoQuality(VideoQuality[] qualities, VideoQualityMenuInterface menu, int originalQualityIndex) {
|
||||
try {
|
||||
boolean useShortsPreference = ShortsPlayerState.isOpen();
|
||||
final int preferredQuality = Utils.getNetworkType() == NetworkType.MOBILE
|
||||
? (useShortsPreference ? shortsQualityMobile : videoQualityMobile).get()
|
||||
: (useShortsPreference ? shortsQualityWifi : videoQualityWifi).get();
|
||||
Utils.verifyOnMainThread();
|
||||
currentMenuInterface = menu;
|
||||
|
||||
if (!userChangedDefaultQuality && preferredQuality == AUTOMATIC_VIDEO_QUALITY_VALUE) {
|
||||
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.
|
||||
}
|
||||
|
||||
if (videoQualities == null || videoQualities.size() != qualities.length) {
|
||||
videoQualities = new ArrayList<>(qualities.length);
|
||||
for (Object streamQuality : qualities) {
|
||||
for (Field field : streamQuality.getClass().getFields()) {
|
||||
if (field.getType().isAssignableFrom(Integer.TYPE)
|
||||
&& field.getName().length() <= 2) {
|
||||
videoQualities.add(field.getInt(streamQuality));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// After changing videos the qualities can initially be for the prior video.
|
||||
// So if the qualities have changed an update is needed.
|
||||
qualityNeedsUpdating = true;
|
||||
Logger.printDebug(() -> "VideoQualities: " + videoQualities);
|
||||
}
|
||||
|
||||
if (userChangedDefaultQuality) {
|
||||
userChangedDefaultQuality = false;
|
||||
final int quality = videoQualities.get(userSelectedQualityIndex);
|
||||
Logger.printDebug(() -> "User changed default quality to: " + quality);
|
||||
changeDefaultQuality(quality);
|
||||
return userSelectedQualityIndex;
|
||||
}
|
||||
|
||||
if (!qualityNeedsUpdating) {
|
||||
// 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 qualityToUse = videoQualities.get(0); // first element is automatic mode
|
||||
int qualityIndexToUse = 0;
|
||||
int i = 0;
|
||||
for (Integer quality : videoQualities) {
|
||||
if (quality <= preferredQuality && qualityToUse < quality) {
|
||||
qualityToUse = quality;
|
||||
qualityIndexToUse = i;
|
||||
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++;
|
||||
}
|
||||
|
||||
// If the desired quality index is equal to the original index,
|
||||
// then the video is already set to the desired default quality.
|
||||
final int qualityToUseFinal = qualityToUse;
|
||||
if (qualityIndexToUse == originalQualityIndex) {
|
||||
// On first load of a new video, if the UI video quality flyout menu
|
||||
// is not updated then it will still show 'Auto' (ie: Auto (480p)),
|
||||
// even though it's already set to the desired resolution.
|
||||
//
|
||||
// To prevent confusion, set the video index anyways (even if it matches the existing index)
|
||||
// as that will force the UI picker to not display "Auto".
|
||||
Logger.printDebug(() -> "Video is already preferred quality: " + qualityToUseFinal);
|
||||
} else {
|
||||
Logger.printDebug(() -> "Changing video quality from: "
|
||||
+ videoQualities.get(originalQualityIndex) + " to: " + qualityToUseFinal);
|
||||
}
|
||||
|
||||
Method m = qInterface.getClass().getMethod(qIndexMethod, Integer.TYPE);
|
||||
m.invoke(qInterface, qualityToUse);
|
||||
return qualityIndexToUse;
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "Failed to set quality", ex);
|
||||
return originalQualityIndex;
|
||||
Logger.printException(() -> "setVideoQuality failure", ex);
|
||||
}
|
||||
return originalQualityIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* @param userSelectedQualityIndex Element index of {@link #currentQualities}.
|
||||
*/
|
||||
public static void userChangedShortsQuality(int userSelectedQualityIndex) {
|
||||
try {
|
||||
if (shouldRememberVideoQuality()) {
|
||||
if (currentQualities == null) {
|
||||
Logger.printDebug(() -> "Cannot save default quality, qualities is null");
|
||||
return;
|
||||
}
|
||||
VideoQuality quality = currentQualities.get(userSelectedQualityIndex);
|
||||
saveDefaultQuality(quality.patch_getResolution());
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "userChangedShortsQuality failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point. Old quality menu.
|
||||
* Injection point. Regular videos.
|
||||
* @param videoResolution Human readable resolution: 480, 720, 1080.
|
||||
*/
|
||||
public static void userChangedQuality(int selectedQualityIndex) {
|
||||
public static void userChangedQuality(int videoResolution) {
|
||||
Utils.verifyOnMainThread();
|
||||
|
||||
if (shouldRememberVideoQuality()) {
|
||||
userSelectedQualityIndex = selectedQualityIndex;
|
||||
userChangedDefaultQuality = true;
|
||||
saveDefaultQuality(videoResolution);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point. New quality menu.
|
||||
*/
|
||||
public static void userChangedQualityInNewFlyout(int selectedQuality) {
|
||||
if (!shouldRememberVideoQuality()) return;
|
||||
|
||||
changeDefaultQuality(selectedQuality); // Quality is human readable resolution (ie: 1080).
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void newVideoStarted(VideoInformation.PlaybackController ignoredPlayerController) {
|
||||
Utils.verifyOnMainThread();
|
||||
|
||||
Logger.printDebug(() -> "newVideoStarted");
|
||||
currentQualities = null;
|
||||
currentQuality = null;
|
||||
currentMenuInterface = null;
|
||||
qualityNeedsUpdating = true;
|
||||
videoQualities = null;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.Animation;
|
||||
@@ -42,7 +41,7 @@ import java.util.function.Function;
|
||||
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.components.PlaybackSpeedMenuFilterPatch;
|
||||
import app.revanced.extension.youtube.patches.components.PlaybackSpeedMenuFilter;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.PlayerType;
|
||||
import kotlin.Unit;
|
||||
@@ -80,6 +79,16 @@ public class CustomPlaybackSpeedPatch {
|
||||
*/
|
||||
public static final float[] customPlaybackSpeeds;
|
||||
|
||||
/**
|
||||
* Minimum and maximum custom playback speeds of {@link #customPlaybackSpeeds}.
|
||||
*/
|
||||
private static final float customPlaybackSpeedsMin, customPlaybackSpeedsMax;
|
||||
|
||||
/**
|
||||
* The last time the old playback menu was forcefully called.
|
||||
*/
|
||||
private static volatile long lastTimeOldPlaybackMenuInvoked;
|
||||
|
||||
/**
|
||||
* Formats speeds to UI strings.
|
||||
*/
|
||||
@@ -90,11 +99,6 @@ public class CustomPlaybackSpeedPatch {
|
||||
*/
|
||||
private static WeakReference<Dialog> currentDialog = new WeakReference<>(null);
|
||||
|
||||
/**
|
||||
* Minimum and maximum custom playback speeds of {@link #customPlaybackSpeeds}.
|
||||
*/
|
||||
private static final float customPlaybackSpeedsMin, customPlaybackSpeedsMax;
|
||||
|
||||
static {
|
||||
// Cap at 2 decimals (rounds automatically).
|
||||
speedFormatter.setMaximumFractionDigits(2);
|
||||
@@ -174,25 +178,33 @@ public class CustomPlaybackSpeedPatch {
|
||||
public static void onFlyoutMenuCreate(RecyclerView recyclerView) {
|
||||
recyclerView.getViewTreeObserver().addOnDrawListener(() -> {
|
||||
try {
|
||||
if (PlaybackSpeedMenuFilterPatch.isPlaybackRateSelectorMenuVisible) {
|
||||
if (hideLithoMenuAndShowCustomSpeedMenu(recyclerView, 5)) {
|
||||
PlaybackSpeedMenuFilterPatch.isPlaybackRateSelectorMenuVisible = false;
|
||||
if (PlaybackSpeedMenuFilter.isPlaybackRateSelectorMenuVisible) {
|
||||
if (hideLithoMenuAndShowSpeedMenu(recyclerView, 5)) {
|
||||
PlaybackSpeedMenuFilter.isPlaybackRateSelectorMenuVisible = false;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "onFlyoutMenuCreate failure", ex);
|
||||
Logger.printException(() -> "isPlaybackRateSelectorMenuVisible failure", ex);
|
||||
}
|
||||
|
||||
try {
|
||||
if (PlaybackSpeedMenuFilter.isOldPlaybackSpeedMenuVisible) {
|
||||
if (hideLithoMenuAndShowSpeedMenu(recyclerView, 8)) {
|
||||
PlaybackSpeedMenuFilter.isOldPlaybackSpeedMenuVisible = false;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "isOldPlaybackSpeedMenuVisible failure", ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private static boolean hideLithoMenuAndShowCustomSpeedMenu(RecyclerView recyclerView, int expectedChildCount) {
|
||||
private static boolean hideLithoMenuAndShowSpeedMenu(RecyclerView recyclerView, int expectedChildCount) {
|
||||
if (recyclerView.getChildCount() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
View firstChild = recyclerView.getChildAt(0);
|
||||
if (!(firstChild instanceof ViewGroup playbackSpeedParentView)) {
|
||||
if (!(recyclerView.getChildAt(0) instanceof ViewGroup playbackSpeedParentView)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -200,33 +212,49 @@ public class CustomPlaybackSpeedPatch {
|
||||
return false;
|
||||
}
|
||||
|
||||
ViewParent parentView3rd = Utils.getParentView(recyclerView, 3);
|
||||
if (!(parentView3rd instanceof ViewGroup)) {
|
||||
return true;
|
||||
if (!(Utils.getParentView(recyclerView, 3) instanceof ViewGroup parentView3rd)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ViewParent parentView4th = parentView3rd.getParent();
|
||||
if (!(parentView4th instanceof ViewGroup)) {
|
||||
return true;
|
||||
if (!(parentView3rd.getParent() instanceof ViewGroup parentView4th)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Dismiss View [R.id.touch_outside] is the 1st ChildView of the 4th ParentView.
|
||||
// This only shows in phone layout.
|
||||
final var touchInsidedView = ((ViewGroup) parentView4th).getChildAt(0);
|
||||
var touchInsidedView = parentView4th.getChildAt(0);
|
||||
touchInsidedView.setSoundEffectsEnabled(false);
|
||||
touchInsidedView.performClick();
|
||||
|
||||
// In tablet layout there is no Dismiss View, instead we just hide all two parent views.
|
||||
((ViewGroup) parentView3rd).setVisibility(View.GONE);
|
||||
((ViewGroup) parentView4th).setVisibility(View.GONE);
|
||||
parentView3rd.setVisibility(View.GONE);
|
||||
parentView4th.setVisibility(View.GONE);
|
||||
|
||||
// Close the litho speed menu and show the modern custom speed dialog.
|
||||
showModernCustomPlaybackSpeedDialog(recyclerView.getContext());
|
||||
Logger.printDebug(() -> "Modern playback speed dialog shown");
|
||||
// Close the litho speed menu and show the custom speeds.
|
||||
if (Settings.RESTORE_OLD_SPEED_MENU.get()) {
|
||||
showOldPlaybackSpeedMenu();
|
||||
Logger.printDebug(() -> "Old playback speed dialog shown");
|
||||
} else {
|
||||
showModernCustomPlaybackSpeedDialog(recyclerView.getContext());
|
||||
Logger.printDebug(() -> "Modern playback speed dialog shown");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void showOldPlaybackSpeedMenu() {
|
||||
// This method is sometimes used multiple times.
|
||||
// To prevent this, ignore method reuse within 1 second.
|
||||
final long now = System.currentTimeMillis();
|
||||
if (now - lastTimeOldPlaybackMenuInvoked < 1000) {
|
||||
Logger.printDebug(() -> "Ignoring call to showOldPlaybackSpeedMenu");
|
||||
return;
|
||||
}
|
||||
lastTimeOldPlaybackMenuInvoked = now;
|
||||
|
||||
// Rest of the implementation added by patch.
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a modern custom dialog for adjusting video playback speed.
|
||||
* <p>
|
||||
@@ -643,11 +671,9 @@ public class CustomPlaybackSpeedPatch {
|
||||
*/
|
||||
public static int getAdjustedBackgroundColor(boolean isHandleBar) {
|
||||
final int baseColor = Utils.getDialogBackgroundColor();
|
||||
float darkThemeFactor = isHandleBar ? 1.25f : 1.115f; // 1.25f for handleBar, 1.115f for others in dark theme.
|
||||
float lightThemeFactor = isHandleBar ? 0.9f : 0.95f; // 0.9f for handleBar, 0.95f for others in light theme.
|
||||
return Utils.isDarkModeEnabled()
|
||||
? Utils.adjustColorBrightness(baseColor, darkThemeFactor) // Lighten for dark theme.
|
||||
: Utils.adjustColorBrightness(baseColor, lightThemeFactor); // Darken for light theme.
|
||||
final float darkThemeFactor = isHandleBar ? 1.25f : 1.115f; // 1.25f for handleBar, 1.115f for others in dark theme.
|
||||
final float lightThemeFactor = isHandleBar ? 0.9f : 0.95f; // 0.9f for handleBar, 0.95f for others in light theme.
|
||||
return Utils.adjustColorBrightness(baseColor, lightThemeFactor, darkThemeFactor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@ import static app.revanced.extension.shared.Utils.getResourceIdentifier;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.util.TypedValue;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toolbar;
|
||||
@@ -24,12 +26,15 @@ import app.revanced.extension.youtube.settings.preference.ReVancedPreferenceFrag
|
||||
* This class is responsible for injecting our own fragment by replacing the LicenseActivity.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class LicenseActivityHook {
|
||||
public class LicenseActivityHook extends Activity {
|
||||
|
||||
private static int currentThemeValueOrdinal = -1; // Must initially be a non-valid enum ordinal value.
|
||||
|
||||
private static ViewGroup.LayoutParams toolbarLayoutParams;
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
public static SearchViewController searchViewController;
|
||||
|
||||
public static void setToolbarLayoutParams(Toolbar toolbar) {
|
||||
if (toolbarLayoutParams != null) {
|
||||
toolbar.setLayoutParams(toolbarLayoutParams);
|
||||
@@ -126,12 +131,13 @@ public class LicenseActivityHook {
|
||||
view -> view instanceof TextView);
|
||||
if (toolbarTextView != null) {
|
||||
toolbarTextView.setTextColor(Utils.getAppForegroundColor());
|
||||
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
|
||||
}
|
||||
setToolbarLayoutParams(toolbar);
|
||||
|
||||
// Add Search Icon and EditText for ReVancedPreferenceFragment only.
|
||||
// Add Search bar only for ReVancedPreferenceFragment.
|
||||
if (fragment instanceof ReVancedPreferenceFragment) {
|
||||
SearchViewController.addSearchViewComponents(activity, toolbar, (ReVancedPreferenceFragment) fragment);
|
||||
searchViewController = SearchViewController.addSearchViewComponents(activity, toolbar, (ReVancedPreferenceFragment) fragment);
|
||||
}
|
||||
|
||||
toolBarParent.addView(toolbar, 0);
|
||||
@@ -166,4 +172,10 @@ public class LicenseActivityHook {
|
||||
Utils.setIsDarkModeEnabled(themeOrdinal == 1);
|
||||
}
|
||||
}
|
||||
|
||||
public static void handleConfigurationChanged(Activity activity, Configuration newConfig) {
|
||||
if (searchViewController != null) {
|
||||
searchViewController.handleOrientationChange(newConfig.orientation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import android.graphics.drawable.GradientDrawable;
|
||||
import android.util.Pair;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
@@ -51,6 +52,7 @@ public class SearchViewController {
|
||||
private final Deque<String> searchHistory;
|
||||
private final AutoCompleteTextView autoCompleteTextView;
|
||||
private final boolean showSettingsSearchHistory;
|
||||
private int currentOrientation;
|
||||
|
||||
/**
|
||||
* Creates a background drawable for the SearchView with rounded corners.
|
||||
@@ -83,8 +85,8 @@ public class SearchViewController {
|
||||
/**
|
||||
* Adds search view components to the activity.
|
||||
*/
|
||||
public static void addSearchViewComponents(Activity activity, Toolbar toolbar, ReVancedPreferenceFragment fragment) {
|
||||
new SearchViewController(activity, toolbar, fragment);
|
||||
public static SearchViewController addSearchViewComponents(Activity activity, Toolbar toolbar, ReVancedPreferenceFragment fragment) {
|
||||
return new SearchViewController(activity, toolbar, fragment);
|
||||
}
|
||||
|
||||
private SearchViewController(Activity activity, Toolbar toolbar, ReVancedPreferenceFragment fragment) {
|
||||
@@ -93,6 +95,7 @@ public class SearchViewController {
|
||||
this.originalTitle = toolbar.getTitle();
|
||||
this.showSettingsSearchHistory = Settings.SETTINGS_SEARCH_HISTORY.get();
|
||||
this.searchHistory = new LinkedList<>();
|
||||
this.currentOrientation = activity.getResources().getConfiguration().orientation;
|
||||
StringSetting searchEntries = Settings.SETTINGS_SEARCH_ENTRIES;
|
||||
if (showSettingsSearchHistory) {
|
||||
String entries = searchEntries.get();
|
||||
@@ -115,6 +118,9 @@ public class SearchViewController {
|
||||
searchView.getContext().getResources().getIdentifier(
|
||||
"android:id/search_src_text", null, null));
|
||||
|
||||
// Disable fullscreen keyboard mode.
|
||||
autoCompleteTextView.setImeOptions(autoCompleteTextView.getImeOptions() | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
|
||||
|
||||
// Set background and query hint.
|
||||
searchView.setBackground(createBackgroundDrawable(toolbar.getContext()));
|
||||
searchView.setQueryHint(str("revanced_settings_search_hint"));
|
||||
@@ -197,7 +203,7 @@ public class SearchViewController {
|
||||
if (isSearchActive) {
|
||||
closeSearch();
|
||||
} else {
|
||||
activity.onBackPressed();
|
||||
activity.finish();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "navigation click failure", ex);
|
||||
@@ -285,6 +291,16 @@ public class SearchViewController {
|
||||
}
|
||||
}
|
||||
|
||||
public void handleOrientationChange(int newOrientation) {
|
||||
if (newOrientation != currentOrientation) {
|
||||
currentOrientation = newOrientation;
|
||||
if (autoCompleteTextView != null) {
|
||||
autoCompleteTextView.dismissDropDown();
|
||||
Logger.printDebug(() -> "Orientation changed, search history dismissed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the search view and shows the keyboard.
|
||||
*/
|
||||
@@ -313,7 +329,7 @@ public class SearchViewController {
|
||||
/**
|
||||
* Closes the search view and hides the keyboard.
|
||||
*/
|
||||
private void closeSearch() {
|
||||
public void closeSearch() {
|
||||
isSearchActive = false;
|
||||
toolbar.getMenu().findItem(getResourceIdentifier(
|
||||
"action_search", "id")).setVisible(true);
|
||||
@@ -326,6 +342,19 @@ public class SearchViewController {
|
||||
imm.hideSoftInputFromWindow(searchView.getWindowToken(), 0);
|
||||
}
|
||||
|
||||
public static boolean handleBackPress() {
|
||||
if (LicenseActivityHook.searchViewController != null
|
||||
&& LicenseActivityHook.searchViewController.isSearchActive()) {
|
||||
LicenseActivityHook.searchViewController.closeSearch();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSearchActive() {
|
||||
return isSearchActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom ArrayAdapter for search history.
|
||||
*/
|
||||
|
||||
@@ -68,8 +68,9 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED = new BooleanSetting("revanced_remember_playback_speed_last_selected", FALSE);
|
||||
public static final BooleanSetting REMEMBER_PLAYBACK_SPEED_LAST_SELECTED_TOAST = new BooleanSetting("revanced_remember_playback_speed_last_selected_toast", TRUE, false,
|
||||
parent(REMEMBER_PLAYBACK_SPEED_LAST_SELECTED));
|
||||
public static final BooleanSetting CUSTOM_SPEED_MENU = new BooleanSetting("revanced_custom_speed_menu", TRUE);
|
||||
public static final FloatSetting PLAYBACK_SPEED_DEFAULT = new FloatSetting("revanced_playback_speed_default", -2.0f);
|
||||
public static final BooleanSetting CUSTOM_SPEED_MENU = new BooleanSetting("revanced_custom_speed_menu", TRUE);
|
||||
public static final BooleanSetting RESTORE_OLD_SPEED_MENU = new BooleanSetting("revanced_restore_old_speed_menu", FALSE, parent(CUSTOM_SPEED_MENU));
|
||||
public static final StringSetting CUSTOM_PLAYBACK_SPEEDS = new StringSetting("revanced_custom_playback_speeds",
|
||||
"0.25\n0.5\n0.75\n1.0\n1.25\n1.5\n1.75\n2.0\n2.5\n3.0\n4.0\n5.0\n6.0\n7.0\n8.0", true);
|
||||
|
||||
@@ -100,7 +101,6 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_CROWDFUNDING_BOX = new BooleanSetting("revanced_hide_crowdfunding_box", FALSE, true);
|
||||
public static final BooleanSetting HIDE_DOODLES = new BooleanSetting("revanced_hide_doodles", FALSE, true, "revanced_hide_doodles_user_dialog_message");
|
||||
public static final BooleanSetting HIDE_EXPANDABLE_CARD = new BooleanSetting("revanced_hide_expandable_card", TRUE);
|
||||
public static final BooleanSetting HIDE_FEED_SURVEY = new BooleanSetting("revanced_hide_feed_survey", TRUE);
|
||||
public static final BooleanSetting HIDE_FILTER_BAR_FEED_IN_FEED = new BooleanSetting("revanced_hide_filter_bar_feed_in_feed", FALSE, true);
|
||||
public static final BooleanSetting HIDE_FILTER_BAR_FEED_IN_HISTORY = new BooleanSetting("revanced_hide_filter_bar_feed_in_history", FALSE);
|
||||
public static final BooleanSetting HIDE_FILTER_BAR_FEED_IN_RELATED_VIDEOS = new BooleanSetting("revanced_hide_filter_bar_feed_in_related_videos", FALSE, true);
|
||||
@@ -113,6 +113,7 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_NOTIFY_ME_BUTTON = new BooleanSetting("revanced_hide_notify_me_button", TRUE);
|
||||
public static final BooleanSetting HIDE_PLAYABLES = new BooleanSetting("revanced_hide_playables", TRUE);
|
||||
public static final BooleanSetting HIDE_SHOW_MORE_BUTTON = new BooleanSetting("revanced_hide_show_more_button", TRUE, true);
|
||||
public static final BooleanSetting HIDE_SURVEYS = new BooleanSetting("revanced_hide_surveys", TRUE);
|
||||
public static final BooleanSetting HIDE_TICKET_SHELF = new BooleanSetting("revanced_hide_ticket_shelf", FALSE);
|
||||
public static final BooleanSetting HIDE_VIDEO_RECOMMENDATION_LABELS = new BooleanSetting("revanced_hide_video_recommendation_labels", TRUE);
|
||||
|
||||
@@ -171,6 +172,7 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_VIDEO_CHANNEL_WATERMARK = new BooleanSetting("revanced_hide_channel_watermark", TRUE);
|
||||
public static final BooleanSetting OPEN_VIDEOS_FULLSCREEN_PORTRAIT = new BooleanSetting("revanced_open_videos_fullscreen_portrait", FALSE);
|
||||
public static final BooleanSetting PLAYBACK_SPEED_DIALOG_BUTTON = new BooleanSetting("revanced_playback_speed_dialog_button", FALSE);
|
||||
public static final BooleanSetting VIDEO_QUALITY_DIALOG_BUTTON = new BooleanSetting("revanced_video_quality_dialog_button", FALSE);
|
||||
public static final IntegerSetting PLAYER_OVERLAY_OPACITY = new IntegerSetting("revanced_player_overlay_opacity", 100, true);
|
||||
public static final BooleanSetting PLAYER_POPUP_PANELS = new BooleanSetting("revanced_hide_player_popup_panels", FALSE);
|
||||
|
||||
@@ -191,7 +193,7 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting EXTERNAL_DOWNLOADER = new BooleanSetting("revanced_external_downloader", FALSE);
|
||||
public static final BooleanSetting EXTERNAL_DOWNLOADER_ACTION_BUTTON = new BooleanSetting("revanced_external_downloader_action_button", FALSE);
|
||||
public static final StringSetting EXTERNAL_DOWNLOADER_PACKAGE_NAME = new StringSetting("revanced_external_downloader_name",
|
||||
"org.schabi.newpipe" /* NewPipe */, parentsAny(EXTERNAL_DOWNLOADER, EXTERNAL_DOWNLOADER_ACTION_BUTTON));
|
||||
"com.deniscerri.ytdl" /* YTDLnis */, parentsAny(EXTERNAL_DOWNLOADER, EXTERNAL_DOWNLOADER_ACTION_BUTTON));
|
||||
|
||||
// Comments
|
||||
public static final BooleanSetting HIDE_COMMENTS_AI_CHAT_SUMMARY = new BooleanSetting("revanced_hide_comments_ai_chat_summary", FALSE);
|
||||
|
||||
@@ -16,10 +16,8 @@ import app.revanced.extension.youtube.settings.Settings;
|
||||
@SuppressWarnings({"unused", "deprecation"})
|
||||
public final class CustomVideoSpeedListPreference extends CustomDialogListPreference {
|
||||
|
||||
/**
|
||||
* Initialize a settings preference list with the available playback speeds.
|
||||
*/
|
||||
private void initializeEntryValues() {
|
||||
{
|
||||
// Initialize a settings preference list with the available playback speeds.
|
||||
float[] customPlaybackSpeeds = CustomPlaybackSpeedPatch.customPlaybackSpeeds;
|
||||
final int numberOfEntries = customPlaybackSpeeds.length + 1;
|
||||
String[] preferenceListEntries = new String[numberOfEntries];
|
||||
@@ -41,10 +39,6 @@ public final class CustomVideoSpeedListPreference extends CustomDialogListPrefer
|
||||
setEntryValues(preferenceListEntryValues);
|
||||
}
|
||||
|
||||
{
|
||||
initializeEntryValues();
|
||||
}
|
||||
|
||||
public CustomVideoSpeedListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,444 @@
|
||||
package app.revanced.extension.youtube.settings.preference;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.sf;
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
import static app.revanced.extension.shared.Utils.dipToPixels;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.graphics.drawable.shapes.RoundRectShape;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Pair;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.preference.CustomDialogListPreference;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
/**
|
||||
* A custom ListPreference for selecting an external downloader package with checkmarks and EditText for custom package names.
|
||||
*/
|
||||
@SuppressWarnings({"unused", "deprecation"})
|
||||
public class ExternalDownloaderPreference extends CustomDialogListPreference {
|
||||
|
||||
/**
|
||||
* Enum representing supported external downloaders with their display names, package names, and download URLs.
|
||||
*/
|
||||
private enum Downloader {
|
||||
YTDLNIS("YTDLnis",
|
||||
"com.deniscerri.ytdl",
|
||||
"https://ytdlnis.org",
|
||||
true),
|
||||
SEAL("Seal",
|
||||
"com.junkfood.seal",
|
||||
"https://github.com/JunkFood02/Seal/releases/latest",
|
||||
true),
|
||||
GRAYJAY("Grayjay",
|
||||
"com.futo.platformplayer",
|
||||
"https://grayjay.app"),
|
||||
LIBRETUBE("LibreTube",
|
||||
"com.github.libretube",
|
||||
"https://libretube.dev"),
|
||||
NEWPIPE("NewPipe",
|
||||
"org.schabi.newpipe",
|
||||
"https://newpipe.net"),
|
||||
PIPEPIPE("PipePipe",
|
||||
"InfinityLoop1309.NewPipeEnhanced",
|
||||
"https://pipepipe.dev"),
|
||||
TUBULAR("Tubular",
|
||||
"org.polymorphicshade.tubular",
|
||||
"https://github.com/polymorphicshade/Tubular/releases/latest"),
|
||||
OTHER(sf("revanced_external_downloader_other_item").toString(),
|
||||
null,
|
||||
null,
|
||||
true);
|
||||
|
||||
private static final Map<String, Downloader> PACKAGE_TO_ENUM = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (Downloader downloader : values()) {
|
||||
String packageName = downloader.packageName;
|
||||
if (packageName != null) {
|
||||
PACKAGE_TO_ENUM.put(packageName, downloader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a Downloader by its package name. This method can never return {@link #OTHER}.
|
||||
* @return The Downloader enum or null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
public static Downloader findByPackageName(String packageName) {
|
||||
return PACKAGE_TO_ENUM.get(Objects.requireNonNull(packageName));
|
||||
}
|
||||
|
||||
public final String name;
|
||||
@Nullable
|
||||
public final String packageName;
|
||||
@Nullable
|
||||
public final String downloadUrl;
|
||||
/**
|
||||
* If a downloader app should be shown in the preference settings
|
||||
* if the app is not currently installed.
|
||||
*/
|
||||
public final boolean isPreferred;
|
||||
|
||||
Downloader(String name, String packageName, String downloadUrl) {
|
||||
this(name, packageName, downloadUrl, false);
|
||||
}
|
||||
|
||||
Downloader(String name, @Nullable String packageName, @Nullable String downloadUrl, boolean isPreferred) {
|
||||
this.name = name;
|
||||
this.packageName = packageName;
|
||||
this.downloadUrl = downloadUrl;
|
||||
this.isPreferred = isPreferred;
|
||||
}
|
||||
|
||||
public boolean isInstalled() {
|
||||
return packageName != null && isAppInstalledAndEnabled(packageName);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isAppInstalledAndEnabled(String packageName) {
|
||||
try {
|
||||
if (Utils.getContext().getPackageManager().getApplicationInfo(packageName, 0).enabled) {
|
||||
Logger.printDebug(() -> "App installed: " + packageName);
|
||||
return true;
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException error) {
|
||||
Logger.printDebug(() -> "App not installed: " + packageName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private EditText editText;
|
||||
private CustomDialogListPreference.ListPreferenceArrayAdapter adapter;
|
||||
|
||||
public ExternalDownloaderPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
public ExternalDownloaderPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public ExternalDownloaderPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public ExternalDownloaderPreference(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
private void updateEntries() {
|
||||
List<CharSequence> entries = new ArrayList<>();
|
||||
List<CharSequence> entryValues = new ArrayList<>();
|
||||
|
||||
for (Downloader downloader : Downloader.values()) {
|
||||
if (downloader.isPreferred || downloader.isInstalled()) {
|
||||
String packageName = downloader.packageName;
|
||||
|
||||
entries.add(downloader.name);
|
||||
entryValues.add(packageName != null
|
||||
? packageName
|
||||
: Downloader.OTHER.name);
|
||||
}
|
||||
}
|
||||
|
||||
setEntries(entries.toArray(new CharSequence[0]));
|
||||
setEntryValues(entryValues.toArray(new CharSequence[0]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the summary for this ListPreference.
|
||||
*/
|
||||
@Override
|
||||
public void setSummary(CharSequence summary) {
|
||||
// Ignore calls to set the summary.
|
||||
// Summary is always the description of the category.
|
||||
//
|
||||
// This is required otherwise the ReVanced preference fragment
|
||||
// sets all ListPreference summaries to show the current selection.
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a custom dialog with a ListView for predefined downloader packages and EditText for custom package input.
|
||||
*/
|
||||
@Override
|
||||
protected void showDialog(@Nullable Bundle state) {
|
||||
// Must set entries before showing the dialog, to handle if
|
||||
// an app is installed while the settings are open in the background.
|
||||
updateEntries();
|
||||
|
||||
Context context = getContext();
|
||||
String packageName = Settings.EXTERNAL_DOWNLOADER_PACKAGE_NAME.get();
|
||||
|
||||
// Create the main layout for the dialog content.
|
||||
LinearLayout contentLayout = new LinearLayout(context);
|
||||
contentLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
// Create ListView for predefined downloader apps.
|
||||
ListView listView = new ListView(context);
|
||||
listView.setId(android.R.id.list);
|
||||
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
|
||||
|
||||
// Create custom adapter for the ListView.
|
||||
final boolean usingCustomDownloader = Downloader.findByPackageName(packageName) == null;
|
||||
adapter = new CustomDialogListPreference.ListPreferenceArrayAdapter(
|
||||
context,
|
||||
Utils.getResourceIdentifier("revanced_custom_list_item_checked", "layout"),
|
||||
getEntries(),
|
||||
getEntryValues(),
|
||||
usingCustomDownloader
|
||||
? Downloader.OTHER.name
|
||||
: packageName
|
||||
);
|
||||
listView.setAdapter(adapter);
|
||||
|
||||
Function<String, Void> updateListViewSelection = (updatedPackageName) -> {
|
||||
String entryValueName = Downloader.findByPackageName(updatedPackageName) == null
|
||||
? Downloader.OTHER.name
|
||||
: updatedPackageName;
|
||||
CharSequence[] entryValues = getEntryValues();
|
||||
|
||||
for (int i = 0, length = entryValues.length; i < length; i++) {
|
||||
String entryString = entryValues[i].toString();
|
||||
if (entryString.equals(entryValueName)) {
|
||||
listView.setItemChecked(i, true);
|
||||
listView.setSelection(i);
|
||||
adapter.setSelectedValue(entryString);
|
||||
adapter.notifyDataSetChanged();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
updateListViewSelection.apply(packageName);
|
||||
|
||||
// Handle item click to select value.
|
||||
listView.setOnItemClickListener((parent, view, position, id) -> {
|
||||
String selectedValue = getEntryValues()[position].toString();
|
||||
Downloader selectedApp = Downloader.findByPackageName(selectedValue);
|
||||
|
||||
if (selectedApp != null) {
|
||||
editText.setText(selectedApp.packageName);
|
||||
editText.setEnabled(false); // Disable editing for predefined options.
|
||||
} else {
|
||||
String savedPackageName = Settings.EXTERNAL_DOWNLOADER_PACKAGE_NAME.get();
|
||||
editText.setText(Downloader.findByPackageName(savedPackageName) == null
|
||||
? savedPackageName // If the user is clicking thru options then retain existing other app.
|
||||
: ""
|
||||
);
|
||||
editText.setEnabled(true); // Enable editing for Custom.
|
||||
editText.requestFocus();
|
||||
}
|
||||
editText.setSelection(editText.getText().length());
|
||||
adapter.setSelectedValue(selectedValue);
|
||||
adapter.notifyDataSetChanged();
|
||||
});
|
||||
|
||||
// Add ListView to content layout with initial height.
|
||||
LinearLayout.LayoutParams listViewParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
0 // Initial height, will be updated.
|
||||
);
|
||||
listViewParams.bottomMargin = dipToPixels(16);
|
||||
contentLayout.addView(listView, listViewParams);
|
||||
|
||||
// Add EditText for custom package name.
|
||||
editText = new EditText(context);
|
||||
editText.setText(packageName);
|
||||
editText.setSelection(packageName.length());
|
||||
editText.setHint(str("revanced_external_downloader_other_item_hint"));
|
||||
editText.setSingleLine(true); // Restrict EditText to a single line.
|
||||
editText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
|
||||
// Set initial EditText state based on selected downloader.
|
||||
editText.setEnabled(usingCustomDownloader);
|
||||
editText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable edit) {
|
||||
String updatedPackageName = edit.toString().trim();
|
||||
updateListViewSelection.apply(updatedPackageName);
|
||||
}
|
||||
});
|
||||
|
||||
ShapeDrawable editTextBackground = new ShapeDrawable(new RoundRectShape(
|
||||
Utils.createCornerRadii(10), null, null));
|
||||
editTextBackground.getPaint().setColor(Utils.getEditTextBackground());
|
||||
final int dip8 = dipToPixels(8);
|
||||
editText.setPadding(dip8, dip8, dip8, dip8);
|
||||
editText.setBackground(editTextBackground);
|
||||
editText.setClipToOutline(true);
|
||||
contentLayout.addView(editText);
|
||||
|
||||
// Create the custom dialog.
|
||||
Pair<Dialog, LinearLayout> dialogPair = Utils.createCustomDialog(
|
||||
context,
|
||||
getTitle() != null ? getTitle().toString() : "",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
() -> {
|
||||
String newValue = editText.getText().toString().trim();
|
||||
if (newValue.isEmpty()) {
|
||||
// Show dialog if EditText is empty.
|
||||
Utils.createCustomDialog(
|
||||
context,
|
||||
str("revanced_external_downloader_name_title"),
|
||||
str("revanced_external_downloader_empty_warning"),
|
||||
null,
|
||||
null,
|
||||
() -> {}, // OK button does nothing (dismiss only).
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
false
|
||||
).first.show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (showDialogIfAppIsNotInstalled(getContext(), newValue)) {
|
||||
return; // Invalid package. Do not save.
|
||||
}
|
||||
|
||||
// Save custom package name.
|
||||
if (callChangeListener(newValue)) {
|
||||
setValue(newValue);
|
||||
}
|
||||
},
|
||||
() -> {}, // Cancel button action (dismiss only).
|
||||
str("revanced_settings_reset"),
|
||||
() -> { // Reset action.
|
||||
String defaultValue = Settings.EXTERNAL_DOWNLOADER_PACKAGE_NAME.defaultValue;
|
||||
editText.setText(defaultValue);
|
||||
editText.setSelection(defaultValue.length());
|
||||
editText.setEnabled(false); // Disable editing on reset.
|
||||
updateListViewSelection.apply(defaultValue);
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
// Add the content layout directly to the dialog's main layout.
|
||||
LinearLayout dialogMainLayout = dialogPair.second;
|
||||
dialogMainLayout.addView(contentLayout, dialogMainLayout.getChildCount() - 1);
|
||||
|
||||
// Update ListView height dynamically based on orientation.
|
||||
//noinspection ExtractMethodRecommender
|
||||
Runnable updateListViewHeight = () -> {
|
||||
int totalHeight = 0;
|
||||
ListAdapter listAdapter = listView.getAdapter();
|
||||
if (listAdapter != null) {
|
||||
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
||||
final int listAdapterCount = listAdapter.getCount();
|
||||
for (int i = 0; i < listAdapterCount; i++) {
|
||||
View item = listAdapter.getView(i, null, listView);
|
||||
item.measure(
|
||||
View.MeasureSpec.makeMeasureSpec(metrics.widthPixels, View.MeasureSpec.AT_MOST),
|
||||
View.MeasureSpec.UNSPECIFIED
|
||||
);
|
||||
totalHeight += item.getMeasuredHeight();
|
||||
}
|
||||
totalHeight += listView.getDividerHeight() * (listAdapterCount - 1);
|
||||
}
|
||||
|
||||
final int orientation = context.getResources().getConfiguration().orientation;
|
||||
if (orientation == android.content.res.Configuration.ORIENTATION_PORTRAIT) {
|
||||
// In portrait orientation, use WRAP_CONTENT for ListView height.
|
||||
listViewParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
|
||||
} else {
|
||||
// In landscape orientation, limit ListView height to 30% of screen height.
|
||||
final int maxHeight = Utils.percentageHeightToPixels(30);
|
||||
listViewParams.height = Math.min(totalHeight, maxHeight);
|
||||
}
|
||||
listView.setLayoutParams(listViewParams);
|
||||
};
|
||||
|
||||
// Initial height calculation.
|
||||
updateListViewHeight.run();
|
||||
|
||||
// Listen for configuration changes (e.g., orientation).
|
||||
View dialogView = dialogPair.second;
|
||||
// Recalculate height when layout changes (e.g., orientation change).
|
||||
dialogView.getViewTreeObserver().addOnGlobalLayoutListener(updateListViewHeight::run);
|
||||
|
||||
// Show the dialog.
|
||||
dialogPair.first.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return If the app is not installed and a dialog was shown.
|
||||
*/
|
||||
public static boolean showDialogIfAppIsNotInstalled(Context context, String packageName) {
|
||||
if (isAppInstalledAndEnabled(packageName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Downloader downloader = Downloader.findByPackageName(packageName);
|
||||
String downloadUrl = downloader != null
|
||||
? downloader.downloadUrl
|
||||
: null;
|
||||
String okButtonText = downloadUrl != null
|
||||
? str("gms_core_dialog_open_website_text") // Open website.
|
||||
: null; // Ok.
|
||||
// Show a dialog if the recommended app is not installed or if the custom package cannot be found.
|
||||
String message = downloader != null
|
||||
? str("revanced_external_downloader_not_installed_warning", downloader.name)
|
||||
: str("revanced_external_downloader_package_not_found_warning", packageName);
|
||||
|
||||
Utils.createCustomDialog(
|
||||
context,
|
||||
str("revanced_external_downloader_not_found_title"),
|
||||
message,
|
||||
null,
|
||||
okButtonText,
|
||||
() -> {
|
||||
try {
|
||||
// OK button action: open the downloader's URL if available.
|
||||
if (downloadUrl != null) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(downloadUrl));
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "Failed to open downloader URL: " + downloader, ex);
|
||||
}
|
||||
},
|
||||
() -> {}, // Cancel button action (dismiss only).
|
||||
null,
|
||||
null,
|
||||
false
|
||||
).first.show();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import android.preference.SwitchPreference;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.BackgroundColorSpan;
|
||||
import android.util.TypedValue;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowInsets;
|
||||
@@ -248,7 +249,15 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
||||
rootView.setOnApplyWindowInsetsListener((v, insets) -> {
|
||||
Insets statusInsets = insets.getInsets(WindowInsets.Type.statusBars());
|
||||
Insets navInsets = insets.getInsets(WindowInsets.Type.navigationBars());
|
||||
v.setPadding(0, statusInsets.top, 0, navInsets.bottom);
|
||||
Insets cutoutInsets = insets.getInsets(WindowInsets.Type.displayCutout());
|
||||
|
||||
// Apply padding for display cutout in landscape.
|
||||
int leftPadding = cutoutInsets.left;
|
||||
int rightPadding = cutoutInsets.right;
|
||||
int topPadding = statusInsets.top;
|
||||
int bottomPadding = navInsets.bottom;
|
||||
|
||||
v.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
|
||||
return insets;
|
||||
});
|
||||
}
|
||||
@@ -265,10 +274,16 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
||||
true, TextView.class::isInstance);
|
||||
if (toolbarTextView != null) {
|
||||
toolbarTextView.setTextColor(Utils.getAppForegroundColor());
|
||||
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
|
||||
}
|
||||
|
||||
LicenseActivityHook.setToolbarLayoutParams(toolbar);
|
||||
|
||||
if (LicenseActivityHook.searchViewController != null
|
||||
&& LicenseActivityHook.searchViewController.isSearchActive()) {
|
||||
toolbar.post(() -> LicenseActivityHook.searchViewController.closeSearch());
|
||||
}
|
||||
|
||||
rootView.addView(toolbar, 0);
|
||||
return false;
|
||||
}
|
||||
@@ -318,10 +333,8 @@ class AbstractPreferenceSearchData<T extends Preference> {
|
||||
return text;
|
||||
}
|
||||
|
||||
final int baseColor = Utils.getAppBackgroundColor();
|
||||
final int adjustedColor = Utils.isDarkModeEnabled()
|
||||
? Utils.adjustColorBrightness(baseColor, 1.20f) // Lighten for dark theme.
|
||||
: Utils.adjustColorBrightness(baseColor, 0.95f); // Darken for light theme.
|
||||
final int adjustedColor = Utils.adjustColorBrightness(Utils.getAppBackgroundColor(),
|
||||
0.95f, 1.20f);
|
||||
BackgroundColorSpan highlightSpan = new BackgroundColorSpan(adjustedColor);
|
||||
|
||||
SpannableStringBuilder spannable = new SpannableStringBuilder(text);
|
||||
|
||||
@@ -830,11 +830,10 @@ public class SegmentPlaybackController {
|
||||
WindowManager.LayoutParams params = window.getAttributes();
|
||||
params.gravity = Gravity.BOTTOM;
|
||||
params.y = dipToPixels(72);
|
||||
DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
|
||||
int portraitWidth = (int) (displayMetrics.widthPixels * 0.6);
|
||||
int portraitWidth = Utils.percentageWidthToPixels(60); // 60% of the screen width.
|
||||
|
||||
if (Resources.getSystem().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
portraitWidth = (int) Math.min(portraitWidth, displayMetrics.heightPixels * 0.6);
|
||||
portraitWidth = Math.min(portraitWidth, Utils.percentageHeightToPixels(60)); // 60% of the screen height.
|
||||
}
|
||||
params.width = portraitWidth;
|
||||
params.dimAmount = 0.0f;
|
||||
|
||||
@@ -9,9 +9,6 @@ import app.revanced.extension.youtube.patches.VideoInformation;
|
||||
import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
import static app.revanced.extension.shared.Utils.showToastShort;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class PlaybackSpeedDialogButton {
|
||||
@Nullable
|
||||
@@ -29,7 +26,11 @@ public class PlaybackSpeedDialogButton {
|
||||
Settings.PLAYBACK_SPEED_DIALOG_BUTTON::get,
|
||||
view -> {
|
||||
try {
|
||||
CustomPlaybackSpeedPatch.showModernCustomPlaybackSpeedDialog(view.getContext());
|
||||
if (Settings.RESTORE_OLD_SPEED_MENU.get()) {
|
||||
CustomPlaybackSpeedPatch.showOldPlaybackSpeedMenu();
|
||||
} else {
|
||||
CustomPlaybackSpeedPatch.showModernCustomPlaybackSpeedDialog(view.getContext());
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "speed button onClick failure", ex);
|
||||
}
|
||||
|
||||
@@ -187,4 +187,56 @@ public class PlayerControlButton {
|
||||
if (view != null) view.setVisibility(View.GONE);
|
||||
isVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the icon of the button.
|
||||
* @param resourceId Drawable identifier, or zero to hide the icon.
|
||||
*/
|
||||
public void setIcon(int resourceId) {
|
||||
try {
|
||||
View button = buttonRef.get();
|
||||
if (button instanceof ImageView imageButton) {
|
||||
imageButton.setImageResource(resourceId);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "setIcon failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts an animation on the button.
|
||||
* @param animation The animation to apply.
|
||||
*/
|
||||
public void startAnimation(Animation animation) {
|
||||
try {
|
||||
View button = buttonRef.get();
|
||||
if (button != null) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,476 @@
|
||||
package app.revanced.extension.youtube.videoplayer;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
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.playback.quality.RememberVideoQualityPatch.VIDEO_QUALITY_1080P_PREMIUM_NAME;
|
||||
import static app.revanced.extension.youtube.patches.playback.quality.RememberVideoQualityPatch.VideoQualityMenuInterface;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.graphics.drawable.shapes.RoundRectShape;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.TranslateAnimation;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.android.libraries.youtube.innertube.model.media.VideoQuality;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.patches.playback.quality.RememberVideoQualityPatch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
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
|
||||
private static PlayerControlButton instance;
|
||||
|
||||
/**
|
||||
* The current resource name of the button icon.
|
||||
*/
|
||||
private static int currentIconResource;
|
||||
|
||||
private static int getDrawableIdentifier(String resourceName) {
|
||||
final int resourceId = Utils.getResourceIdentifier(resourceName, "drawable");
|
||||
if (resourceId == 0) Logger.printException(() -> "Could not find resource: " + resourceName);
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void initializeButton(View controlsView) {
|
||||
try {
|
||||
instance = new PlayerControlButton(
|
||||
controlsView,
|
||||
"revanced_video_quality_dialog_button",
|
||||
"revanced_video_quality_dialog_button_placeholder",
|
||||
Settings.VIDEO_QUALITY_DIALOG_BUTTON::get,
|
||||
view -> {
|
||||
try {
|
||||
showVideoQualityDialog(view.getContext());
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "Video quality button onClick failure", ex);
|
||||
}
|
||||
},
|
||||
view -> {
|
||||
try {
|
||||
List<VideoQuality> qualities = RememberVideoQualityPatch.getCurrentQualities();
|
||||
VideoQualityMenuInterface menu = RememberVideoQualityPatch.getCurrentMenuInterface();
|
||||
if (qualities == null || menu == null) {
|
||||
Logger.printDebug(() -> "Cannot reset quality, videoQualities is null");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Reset to default quality.
|
||||
final int defaultResolution = RememberVideoQualityPatch.getDefaultQualityResolution();
|
||||
for (VideoQuality quality : qualities) {
|
||||
final int resolution = quality.patch_getResolution();
|
||||
if (resolution != AUTOMATIC_VIDEO_QUALITY_VALUE && resolution <= defaultResolution) {
|
||||
Logger.printDebug(() -> "Resetting quality to: " + quality);
|
||||
menu.patch_setQuality(quality);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Existing hook cannot set default quality to auto.
|
||||
// Instead show the quality dialog.
|
||||
showVideoQualityDialog(view.getContext());
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "Video quality button reset failure", ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
// Set initial icon.
|
||||
updateButtonIcon(RememberVideoQualityPatch.getCurrentQuality());
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "initializeButton failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void setVisibilityImmediate(boolean visible) {
|
||||
if (instance != null) {
|
||||
instance.setVisibilityImmediate(visible);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void setVisibility(boolean visible, boolean animated) {
|
||||
if (instance != null) {
|
||||
instance.setVisibility(visible, animated);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a dialog with available video qualities, excluding Auto, with a title showing the current quality.
|
||||
*/
|
||||
private static void showVideoQualityDialog(Context context) {
|
||||
try {
|
||||
List<VideoQuality> currentQualities = RememberVideoQualityPatch.getCurrentQualities();
|
||||
VideoQuality currentQuality = RememberVideoQualityPatch.getCurrentQuality();
|
||||
if (currentQualities == null || currentQuality == null) {
|
||||
Logger.printDebug(() -> "Cannot show qualities dialog, videoQualities is null");
|
||||
return;
|
||||
}
|
||||
if (currentQualities.size() < 2) {
|
||||
// Should never happen.
|
||||
Logger.printException(() -> "Cannot show qualities dialog, no qualities available");
|
||||
return;
|
||||
}
|
||||
|
||||
VideoQualityMenuInterface menu = RememberVideoQualityPatch.getCurrentMenuInterface();
|
||||
if (menu == null) {
|
||||
Logger.printDebug(() -> "Cannot show qualities dialog, menu is null");
|
||||
return;
|
||||
}
|
||||
|
||||
// -1 adjustment for automatic quality at first index.
|
||||
final int listViewSelectedIndex = currentQualities.indexOf(currentQuality) - 1;
|
||||
|
||||
List<String> qualityLabels = new ArrayList<>(currentQualities.size() - 1);
|
||||
for (VideoQuality availableQuality : currentQualities) {
|
||||
if (availableQuality.patch_getResolution() != AUTOMATIC_VIDEO_QUALITY_VALUE) {
|
||||
qualityLabels.add(availableQuality.patch_getQualityName());
|
||||
}
|
||||
}
|
||||
|
||||
Dialog dialog = new Dialog(context);
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setCanceledOnTouchOutside(true);
|
||||
dialog.setCancelable(true);
|
||||
|
||||
final int dip4 = dipToPixels(4); // Height for handle bar.
|
||||
final int dip5 = dipToPixels(5); // Padding for mainLayout.
|
||||
final int dip6 = dipToPixels(6); // Bottom margin.
|
||||
final int dip8 = dipToPixels(8); // Side padding.
|
||||
final int dip16 = dipToPixels(16); // Left padding for ListView.
|
||||
final int dip20 = dipToPixels(20); // Margin below handle.
|
||||
final int dip40 = dipToPixels(40); // Width for handle bar.
|
||||
|
||||
LinearLayout mainLayout = new LinearLayout(context);
|
||||
mainLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
mainLayout.setPadding(dip5, dip8, dip5, dip8);
|
||||
|
||||
ShapeDrawable background = new ShapeDrawable(new RoundRectShape(
|
||||
Utils.createCornerRadii(12), null, null));
|
||||
background.getPaint().setColor(Utils.getDialogBackgroundColor());
|
||||
mainLayout.setBackground(background);
|
||||
|
||||
View handleBar = new View(context);
|
||||
ShapeDrawable handleBackground = new ShapeDrawable(new RoundRectShape(
|
||||
Utils.createCornerRadii(4), null, null));
|
||||
final int baseColor = Utils.getDialogBackgroundColor();
|
||||
final int adjustedHandleBarBackgroundColor = Utils.adjustColorBrightness(
|
||||
baseColor, 0.9f, 1.25f);
|
||||
handleBackground.getPaint().setColor(adjustedHandleBarBackgroundColor);
|
||||
handleBar.setBackground(handleBackground);
|
||||
LinearLayout.LayoutParams handleParams = new LinearLayout.LayoutParams(dip40, dip4);
|
||||
handleParams.gravity = Gravity.CENTER_HORIZONTAL;
|
||||
handleParams.setMargins(0, 0, 0, dip20);
|
||||
handleBar.setLayoutParams(handleParams);
|
||||
mainLayout.addView(handleBar);
|
||||
|
||||
// Create SpannableStringBuilder for formatted text.
|
||||
SpannableStringBuilder spannableTitle = new SpannableStringBuilder();
|
||||
String titlePart = str("video_quality_quick_menu_title");
|
||||
String separatorPart = str("video_quality_title_seperator");
|
||||
|
||||
// Append title part with default foreground color.
|
||||
spannableTitle.append(titlePart);
|
||||
spannableTitle.setSpan(
|
||||
new ForegroundColorSpan(Utils.getAppForegroundColor()),
|
||||
0,
|
||||
titlePart.length(),
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
);
|
||||
spannableTitle.append(" "); // Space after title.
|
||||
|
||||
// Append separator part with adjusted title color.
|
||||
int separatorStart = spannableTitle.length();
|
||||
spannableTitle.append(separatorPart);
|
||||
final int adjustedTitleForegroundColor = Utils.adjustColorBrightness(
|
||||
Utils.getAppForegroundColor(), 1.6f, 0.6f);
|
||||
spannableTitle.setSpan(
|
||||
new ForegroundColorSpan(adjustedTitleForegroundColor),
|
||||
separatorStart,
|
||||
separatorStart + separatorPart.length(),
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
);
|
||||
spannableTitle.append(" "); // Space after separator.
|
||||
|
||||
// Append quality label with adjusted title color.
|
||||
final int qualityStart = spannableTitle.length();
|
||||
spannableTitle.append(currentQuality.patch_getQualityName());
|
||||
spannableTitle.setSpan(
|
||||
new ForegroundColorSpan(adjustedTitleForegroundColor),
|
||||
qualityStart,
|
||||
qualityStart + currentQuality.patch_getQualityName().length(),
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
);
|
||||
|
||||
// Add title with current quality.
|
||||
TextView titleView = new TextView(context);
|
||||
titleView.setText(spannableTitle);
|
||||
titleView.setTextSize(16);
|
||||
// Remove setTextColor since color is handled by SpannableStringBuilder.
|
||||
LinearLayout.LayoutParams titleParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
titleParams.setMargins(dip8, 0, 0, dip20);
|
||||
titleView.setLayoutParams(titleParams);
|
||||
mainLayout.addView(titleView);
|
||||
|
||||
ListView listView = new ListView(context);
|
||||
CustomQualityAdapter adapter = new CustomQualityAdapter(context, qualityLabels);
|
||||
adapter.setSelectedPosition(listViewSelectedIndex);
|
||||
listView.setAdapter(adapter);
|
||||
listView.setDivider(null);
|
||||
listView.setPadding(dip16, 0, 0, 0);
|
||||
|
||||
listView.setOnItemClickListener((parent, view, which, id) -> {
|
||||
try {
|
||||
final int originalIndex = which + 1; // Adjust for automatic.
|
||||
VideoQuality selectedQuality = currentQualities.get(originalIndex);
|
||||
Logger.printDebug(() -> "User clicked on quality: " + 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();
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "Video quality selection failure", ex);
|
||||
}
|
||||
});
|
||||
|
||||
LinearLayout.LayoutParams listViewParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
listViewParams.setMargins(0, 0, 0, dip5);
|
||||
listView.setLayoutParams(listViewParams);
|
||||
mainLayout.addView(listView);
|
||||
|
||||
LinearLayout wrapperLayout = new LinearLayout(context);
|
||||
wrapperLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
wrapperLayout.setPadding(dip8, 0, dip8, 0);
|
||||
wrapperLayout.addView(mainLayout);
|
||||
dialog.setContentView(wrapperLayout);
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
WindowManager.LayoutParams params = window.getAttributes();
|
||||
params.gravity = Gravity.BOTTOM;
|
||||
params.y = dip6;
|
||||
int portraitWidth = context.getResources().getDisplayMetrics().widthPixels;
|
||||
if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
portraitWidth = Math.min(
|
||||
portraitWidth,
|
||||
context.getResources().getDisplayMetrics().heightPixels);
|
||||
}
|
||||
params.width = portraitWidth;
|
||||
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
||||
window.setAttributes(params);
|
||||
window.setBackgroundDrawable(null);
|
||||
}
|
||||
|
||||
final int fadeDurationFast = Utils.getResourceInteger("fade_duration_fast");
|
||||
Animation slideInABottomAnimation = Utils.getResourceAnimation("slide_in_bottom");
|
||||
slideInABottomAnimation.setDuration(fadeDurationFast);
|
||||
mainLayout.startAnimation(slideInABottomAnimation);
|
||||
|
||||
// noinspection ClickableViewAccessibility
|
||||
mainLayout.setOnTouchListener(new View.OnTouchListener() {
|
||||
final float dismissThreshold = dipToPixels(100);
|
||||
float touchY;
|
||||
float translationY;
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
touchY = event.getRawY();
|
||||
translationY = mainLayout.getTranslationY();
|
||||
return true;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
final float deltaY = event.getRawY() - touchY;
|
||||
if (deltaY >= 0) {
|
||||
mainLayout.setTranslationY(translationY + deltaY);
|
||||
}
|
||||
return true;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
if (mainLayout.getTranslationY() > dismissThreshold) {
|
||||
//noinspection ExtractMethodRecommender
|
||||
final float remainingDistance = context.getResources().getDisplayMetrics().heightPixels
|
||||
- mainLayout.getTop();
|
||||
TranslateAnimation slideOut = new TranslateAnimation(
|
||||
0, 0, mainLayout.getTranslationY(), remainingDistance);
|
||||
slideOut.setDuration(fadeDurationFast);
|
||||
slideOut.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {}
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {}
|
||||
});
|
||||
mainLayout.startAnimation(slideOut);
|
||||
} else {
|
||||
TranslateAnimation slideBack = new TranslateAnimation(
|
||||
0, 0, mainLayout.getTranslationY(), 0);
|
||||
slideBack.setDuration(fadeDurationFast);
|
||||
mainLayout.startAnimation(slideBack);
|
||||
mainLayout.setTranslationY(0);
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "showVideoQualityDialog failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static class CustomQualityAdapter extends ArrayAdapter<String> {
|
||||
private int selectedPosition = -1;
|
||||
|
||||
public CustomQualityAdapter(@NonNull Context context, @NonNull List<String> objects) {
|
||||
super(context, 0, objects);
|
||||
}
|
||||
|
||||
private void setSelectedPosition(int position) {
|
||||
this.selectedPosition = position;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
|
||||
ViewHolder viewHolder;
|
||||
|
||||
if (convertView == null) {
|
||||
convertView = LayoutInflater.from(getContext()).inflate(
|
||||
Utils.getResourceIdentifier("revanced_custom_list_item_checked", "layout"),
|
||||
parent,
|
||||
false
|
||||
);
|
||||
viewHolder = new ViewHolder();
|
||||
viewHolder.checkIcon = convertView.findViewById(
|
||||
Utils.getResourceIdentifier("revanced_check_icon", "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);
|
||||
} else {
|
||||
viewHolder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
|
||||
viewHolder.textView.setText(getItem(position));
|
||||
final boolean isSelected = position == selectedPosition;
|
||||
viewHolder.checkIcon.setVisibility(isSelected ? View.VISIBLE : View.GONE);
|
||||
viewHolder.placeholder.setVisibility(isSelected ? View.GONE : View.INVISIBLE);
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
private static class ViewHolder {
|
||||
ImageView checkIcon;
|
||||
View placeholder;
|
||||
TextView textView;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.google.android.libraries.youtube.innertube.model.media;
|
||||
|
||||
public abstract class VideoQuality implements Comparable<VideoQuality> {
|
||||
public abstract String patch_getQualityName();
|
||||
|
||||
public abstract int patch_getResolution();
|
||||
}
|
||||
|
||||
@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
|
||||
org.gradle.parallel = true
|
||||
android.useAndroidX = true
|
||||
kotlin.code.style = official
|
||||
version = 5.31.2-dev.2
|
||||
version = 5.33.0-dev.8
|
||||
|
||||
9
package-lock.json
generated
9
package-lock.json
generated
@@ -9,7 +9,7 @@
|
||||
"@semantic-release/changelog": "^6.0.3",
|
||||
"@semantic-release/git": "^10.0.1",
|
||||
"gradle-semantic-release-plugin": "^1.10.1",
|
||||
"semantic-release": "^24.2.6"
|
||||
"semantic-release": "^24.2.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
@@ -6889,10 +6889,11 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/semantic-release": {
|
||||
"version": "24.2.6",
|
||||
"resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.2.6.tgz",
|
||||
"integrity": "sha512-D0cwjlO5RZzHHxAcsoF1HxiRLfC3ehw+ay+zntzFs6PNX6aV0JzKNG15mpxPipBYa/l4fHly88dHvgDyqwb1Ww==",
|
||||
"version": "24.2.7",
|
||||
"resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.2.7.tgz",
|
||||
"integrity": "sha512-g7RssbTAbir1k/S7uSwSVZFfFXwpomUB9Oas0+xi9KStSCmeDXcA7rNhiskjLqvUe/Evhx8fVCT16OSa34eM5g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@semantic-release/commit-analyzer": "^13.0.0-beta.1",
|
||||
"@semantic-release/error": "^4.0.0",
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
"@semantic-release/changelog": "^6.0.3",
|
||||
"@semantic-release/git": "^10.0.1",
|
||||
"gradle-semantic-release-plugin": "^1.10.1",
|
||||
"semantic-release": "^24.2.6"
|
||||
"semantic-release": "^24.2.7"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,6 +424,10 @@ public final class app/revanced/patches/openinghours/misc/fix/crash/FixCrashPatc
|
||||
public static final fun getFixCrashPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/orfon/detection/root/RemoveRootDetectionPatchKt {
|
||||
public static final fun getRemoveRootDetectionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/pandora/ads/DisableAudioAdsPatchKt {
|
||||
public static final fun getDisableAudioAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -476,6 +480,10 @@ public final class app/revanced/patches/primevideo/misc/permissions/RenamePermis
|
||||
public static final fun getRenamePermissionsPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/primevideo/video/speed/PlaybackSpeedPatchKt {
|
||||
public static final fun getPlaybackSpeedPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/protonmail/account/RemoveFreeAccountsLimitPatchKt {
|
||||
public static final fun getRemoveFreeAccountsLimitPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
}
|
||||
@@ -1238,6 +1246,7 @@ public final class app/revanced/patches/youtube/interaction/dialog/RemoveViewerD
|
||||
|
||||
public final class app/revanced/patches/youtube/interaction/doubletap/DisableChapterSkipDoubleTapPatchKt {
|
||||
public static final fun getDisableChapterSkipDoubleTapPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun getDisableDoubleTapActionsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/interaction/downloads/DownloadsPatchKt {
|
||||
@@ -1655,6 +1664,10 @@ public final class app/revanced/patches/youtube/video/quality/VideoQualityPatchK
|
||||
public static final fun getVideoQualityPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/video/quality/button/VideoQualityDialogButtonPatchKt {
|
||||
public static final fun getVideoQualityButtonPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/video/speed/PlaybackSpeedPatchKt {
|
||||
public static final fun getPlaybackSpeedPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ internal val createInboxSubTabsFingerprint = fingerprint {
|
||||
}
|
||||
|
||||
internal val loadInboxAdsFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returns("V")
|
||||
strings(
|
||||
"ads_load_begin",
|
||||
|
||||
@@ -8,12 +8,7 @@ val hideVideoAdsPatch = bytecodePatch(
|
||||
name = "Hide music video ads",
|
||||
description = "Hides ads that appear while listening to or streaming music videos, podcasts, or songs.",
|
||||
) {
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.16.53",
|
||||
"8.05.51"
|
||||
)
|
||||
)
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
|
||||
execute {
|
||||
navigate(showVideoAdsParentFingerprint.originalMethod)
|
||||
|
||||
@@ -8,12 +8,7 @@ val enableExclusiveAudioPlaybackPatch = bytecodePatch(
|
||||
name = "Enable exclusive audio playback",
|
||||
description = "Enables the option to play audio without video.",
|
||||
) {
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.16.53",
|
||||
"8.05.51"
|
||||
)
|
||||
)
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
|
||||
execute {
|
||||
allowExclusiveAudioPlaybackFingerprint.method.returnEarly(true)
|
||||
|
||||
@@ -11,12 +11,7 @@ val permanentRepeatPatch = bytecodePatch(
|
||||
description = "Permanently remember your repeating preference even if the playlist ends or another track is played.",
|
||||
use = false,
|
||||
) {
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.16.53",
|
||||
"8.05.51"
|
||||
)
|
||||
)
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
|
||||
execute {
|
||||
val startIndex = repeatTrackFingerprint.patternMatch!!.endIndex
|
||||
|
||||
@@ -7,18 +7,9 @@ import app.revanced.patcher.patch.bytecodePatch
|
||||
@Suppress("unused")
|
||||
val permanentShufflePatch = bytecodePatch(
|
||||
description = "Permanently remember your shuffle preference " +
|
||||
"even if the playlist ends or another track is played.",
|
||||
use = false,
|
||||
"even if the playlist ends or another track is played."
|
||||
) {
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"6.45.54",
|
||||
"6.51.53",
|
||||
"7.01.53",
|
||||
"7.02.52",
|
||||
"7.03.52",
|
||||
),
|
||||
)
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
|
||||
execute {
|
||||
disableShuffleFingerprint.method.addInstruction(0, "return-void")
|
||||
|
||||
@@ -11,12 +11,7 @@ val hideCategoryBar = bytecodePatch(
|
||||
description = "Hides the category bar at the top of the homepage.",
|
||||
use = false,
|
||||
) {
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.16.53",
|
||||
"8.05.51"
|
||||
)
|
||||
)
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
|
||||
execute {
|
||||
constructCategoryBarFingerprint.method.apply {
|
||||
|
||||
@@ -11,12 +11,7 @@ val hideGetPremiumPatch = bytecodePatch(
|
||||
name = "Hide 'Get Music Premium' label",
|
||||
description = "Hides the \"Get Music Premium\" label from the account menu and settings.",
|
||||
) {
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.16.53",
|
||||
"8.05.51"
|
||||
)
|
||||
)
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
|
||||
execute {
|
||||
hideGetPremiumFingerprint.method.apply {
|
||||
|
||||
@@ -18,12 +18,7 @@ val removeUpgradeButtonPatch = bytecodePatch(
|
||||
name = "Remove upgrade button",
|
||||
description = "Removes the upgrade tab from the pivot bar.",
|
||||
) {
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.16.53",
|
||||
"8.05.51"
|
||||
)
|
||||
)
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
|
||||
execute {
|
||||
pivotBarConstructorFingerprint.method.apply {
|
||||
|
||||
@@ -8,12 +8,7 @@ val bypassCertificateChecksPatch = bytecodePatch(
|
||||
name = "Bypass certificate checks",
|
||||
description = "Bypasses certificate checks which prevent YouTube Music from working on Android Auto.",
|
||||
) {
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.16.53",
|
||||
"8.05.51"
|
||||
)
|
||||
)
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
|
||||
execute {
|
||||
checkCertificateFingerprint.method.returnEarly(true)
|
||||
|
||||
@@ -8,12 +8,7 @@ val backgroundPlaybackPatch = bytecodePatch(
|
||||
name = "Remove background playback restrictions",
|
||||
description = "Removes restrictions on background playback, including playing kids videos in the background.",
|
||||
) {
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.16.53",
|
||||
"8.05.51"
|
||||
)
|
||||
)
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
|
||||
execute {
|
||||
kidsBackgroundPlaybackPolicyControllerFingerprint.method.addInstruction(
|
||||
|
||||
@@ -25,12 +25,7 @@ val spoofClientPatch = bytecodePatch(
|
||||
name = "Spoof client",
|
||||
description = "Spoofs the client to fix playback.",
|
||||
) {
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.16.53",
|
||||
"8.05.51"
|
||||
)
|
||||
)
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
|
||||
@@ -3,6 +3,7 @@ package app.revanced.patches.nfctoolsse.misc.pro
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
@Deprecated("This patch no longer works and will soon be deleted.")
|
||||
internal val isLicenseRegisteredFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC)
|
||||
returns("Z")
|
||||
|
||||
@@ -4,9 +4,8 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
|
||||
@Suppress("unused")
|
||||
val unlockProPatch = bytecodePatch(
|
||||
name = "Unlock pro",
|
||||
) {
|
||||
@Deprecated("This patch no longer works and will soon be deleted.")
|
||||
val unlockProPatch = bytecodePatch{
|
||||
compatibleWith("com.wakdev.apps.nfctools.se")
|
||||
|
||||
execute {
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.orfon.detection.root
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val isDeviceRootedFingeprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC)
|
||||
returns("Z")
|
||||
custom { method, classDef ->
|
||||
method.name == "isDeviceRooted" &&
|
||||
classDef.endsWith("/RootChecker;")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package app.revanced.patches.orfon.detection.root
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
val removeRootDetectionPatch = bytecodePatch(
|
||||
name = "Remove root detection",
|
||||
description = "Removes the check for root permissions.",
|
||||
) {
|
||||
compatibleWith("com.nousguide.android.orftvthek")
|
||||
|
||||
execute {
|
||||
isDeviceRootedFingeprint.method.returnEarly(false)
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ val skipAdsPatch = bytecodePatch(
|
||||
name = "Skip ads",
|
||||
description = "Automatically skips video stream ads.",
|
||||
) {
|
||||
compatibleWith("com.amazon.avod.thirdpartyclient"("3.0.403.257"))
|
||||
compatibleWith("com.amazon.avod.thirdpartyclient"("3.0.412.2947"))
|
||||
|
||||
dependsOn(sharedExtensionPatch)
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package app.revanced.patches.primevideo.video.speed
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val playbackUserControlsInitializeFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC)
|
||||
parameters("Lcom/amazon/avod/playbackclient/PlaybackInitializationContext;")
|
||||
returns("V")
|
||||
custom { method, classDef ->
|
||||
method.name == "initialize" && classDef.type == "Lcom/amazon/avod/playbackclient/activity/feature/PlaybackUserControlsFeature;"
|
||||
}
|
||||
}
|
||||
|
||||
internal val playbackUserControlsPrepareForPlaybackFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC)
|
||||
parameters("Lcom/amazon/avod/playbackclient/PlaybackContext;")
|
||||
returns("V")
|
||||
custom { method, classDef ->
|
||||
method.name == "prepareForPlayback" &&
|
||||
classDef.type == "Lcom/amazon/avod/playbackclient/activity/feature/PlaybackUserControlsFeature;"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package app.revanced.patches.primevideo.video.speed
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.primevideo.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/primevideo/videoplayer/PlaybackSpeedPatch;"
|
||||
|
||||
val playbackSpeedPatch = bytecodePatch(
|
||||
name = "Playback speed",
|
||||
description = "Adds playback speed controls to the video player.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.amazon.avod.thirdpartyclient"("3.0.412.2947")
|
||||
)
|
||||
|
||||
execute {
|
||||
playbackUserControlsInitializeFingerprint.method.apply {
|
||||
val getIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.IPUT_OBJECT &&
|
||||
getReference<FieldReference>()?.name == "mUserControls"
|
||||
}
|
||||
|
||||
val getRegister = getInstruction<OneRegisterInstruction>(getIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
getIndex + 1,
|
||||
"""
|
||||
invoke-static { v$getRegister }, $EXTENSION_CLASS_DESCRIPTOR->initializeSpeedOverlay(Landroid/view/View;)V
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
playbackUserControlsPrepareForPlaybackFingerprint.method.apply {
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-virtual { p1 }, Lcom/amazon/avod/playbackclient/PlaybackContext;->getPlayer()Lcom/amazon/video/sdk/player/Player;
|
||||
move-result-object v0
|
||||
invoke-static { v0 }, $EXTENSION_CLASS_DESCRIPTOR->setPlayer(Lcom/amazon/video/sdk/player/Player;)V
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,7 +148,7 @@ fun gmsCoreSupportPatch(
|
||||
|
||||
fun packageNameTransform(fromPackageName: String, toPackageName: String): (String) -> String? = { string ->
|
||||
when (string) {
|
||||
"$fromPackageName.SuggestionsProvider",
|
||||
"$fromPackageName.SuggestionProvider",
|
||||
"$fromPackageName.fileprovider",
|
||||
-> string.replace(fromPackageName, toPackageName)
|
||||
|
||||
|
||||
@@ -11,6 +11,22 @@ internal val loadOrbitLibraryFingerprint = fingerprint {
|
||||
strings("/liborbit-jni-spotify.so")
|
||||
}
|
||||
|
||||
internal val setClientIdFingerprint = fingerprint {
|
||||
parameters("Ljava/lang/String;")
|
||||
custom { method, classDef ->
|
||||
classDef.type == "Lcom/spotify/connectivity/ApplicationScopeConfiguration;"
|
||||
&& method.name == "setClientId"
|
||||
}
|
||||
}
|
||||
|
||||
internal val setUserAgentFingerprint = fingerprint {
|
||||
parameters("Ljava/lang/String;")
|
||||
custom { method, classDef ->
|
||||
classDef.type == "Lcom/spotify/connectivity/ApplicationScopeConfiguration;"
|
||||
&& method.name == "setDefaultHTTPUserAgent"
|
||||
}
|
||||
}
|
||||
|
||||
internal val extensionFixConstantsFingerprint = fingerprint {
|
||||
custom { _, classDef -> classDef.type == "Lapp/revanced/extension/spotify/misc/fix/Constants;" }
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.revanced.patches.spotify.misc.fix
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.intOption
|
||||
@@ -72,7 +73,29 @@ val spoofClientPatch = bytecodePatch(
|
||||
compatibleWith("com.spotify.music")
|
||||
|
||||
execute {
|
||||
// region Spoof client.
|
||||
val clientVersion = clientVersion!!
|
||||
val hardwareMachine = hardwareMachine!!
|
||||
val systemVersion = systemVersion!!
|
||||
|
||||
// region Spoof login request.
|
||||
|
||||
val version = clientVersion
|
||||
.substringAfter('-')
|
||||
.substringBeforeLast('.')
|
||||
.substringBeforeLast('.')
|
||||
|
||||
setUserAgentFingerprint.method.addInstruction(
|
||||
0,
|
||||
"const-string p1, \"Spotify/$version iOS/$systemVersion ($hardwareMachine)\""
|
||||
)
|
||||
|
||||
setClientIdFingerprint.method.addInstruction(
|
||||
0, "const-string p1, \"58bd3c95768941ea9eb4350aaa033eb3\""
|
||||
)
|
||||
|
||||
// endregion
|
||||
|
||||
// region Spoof client-token request.
|
||||
|
||||
loadOrbitLibraryFingerprint.method.addInstructions(
|
||||
0,
|
||||
@@ -83,9 +106,9 @@ val spoofClientPatch = bytecodePatch(
|
||||
)
|
||||
|
||||
mapOf(
|
||||
"getClientVersion" to clientVersion!!,
|
||||
"getSystemVersion" to systemVersion!!,
|
||||
"getHardwareMachine" to hardwareMachine!!
|
||||
"getClientVersion" to clientVersion,
|
||||
"getSystemVersion" to systemVersion,
|
||||
"getHardwareMachine" to hardwareMachine
|
||||
).forEach { (methodName, value) ->
|
||||
extensionFixConstantsFingerprint.classDef.methods.single { it.name == methodName }.returnEarly(value)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.revanced.patches.youtube.interaction.doubletap
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
@@ -8,12 +9,14 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/DisableChapterSkipDoubleTapPatch;"
|
||||
"Lapp/revanced/extension/youtube/patches/DisableDoubleTapActionsPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val disableChapterSkipDoubleTapPatch = bytecodePatch(
|
||||
val disableDoubleTapActionsPatch = bytecodePatch(
|
||||
name = "Disable double tap actions",
|
||||
description = "Adds an option to disable player double tap gestures.",
|
||||
) {
|
||||
@@ -25,9 +28,6 @@ val disableChapterSkipDoubleTapPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
"20.12.46",
|
||||
"20.13.41",
|
||||
@@ -35,12 +35,28 @@ val disableChapterSkipDoubleTapPatch = bytecodePatch(
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("youtube", "interaction.doubletap.disableChapterSkipDoubleTapPatch")
|
||||
addResources("youtube", "interaction.doubletap.disableDoubleTapActionsPatch")
|
||||
|
||||
PreferenceScreen.PLAYER.addPreferences(
|
||||
SwitchPreference("revanced_disable_chapter_skip_double_tap"),
|
||||
)
|
||||
|
||||
val doubleTapInfoGetSeekSourceFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
parameters("Z")
|
||||
returns(seekTypeEnumFingerprint.originalClassDef.type)
|
||||
opcodes(
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.RETURN_OBJECT,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.RETURN_OBJECT,
|
||||
)
|
||||
custom { _, classDef ->
|
||||
classDef.fields.count() == 4
|
||||
}
|
||||
}
|
||||
|
||||
// Force isChapterSeek flag to false.
|
||||
doubleTapInfoGetSeekSourceFingerprint.method.addInstructions(
|
||||
0,
|
||||
@@ -60,4 +76,9 @@ val disableChapterSkipDoubleTapPatch = bytecodePatch(
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Patch was renamed", ReplaceWith("disableDoubleTapActionsPatch"))
|
||||
val disableChapterSkipDoubleTapPatch = bytecodePatch {
|
||||
dependsOn(disableDoubleTapActionsPatch)
|
||||
}
|
||||
|
||||
@@ -2,22 +2,13 @@ package app.revanced.patches.youtube.interaction.doubletap
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val doubleTapInfoGetSeekSourceFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
parameters("Z")
|
||||
returns("L") // Enum SeekSource, but name obfuscated.
|
||||
opcodes(
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.RETURN_OBJECT,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.RETURN_OBJECT,
|
||||
internal val seekTypeEnumFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)
|
||||
strings(
|
||||
"SEEK_SOURCE_SEEK_TO_NEXT_CHAPTER",
|
||||
"SEEK_SOURCE_SEEK_TO_PREVIOUS_CHAPTER"
|
||||
)
|
||||
custom { _, classDef ->
|
||||
classDef.fields.count() == 4
|
||||
}
|
||||
}
|
||||
|
||||
internal val doubleTapInfoCtorFingerprint = fingerprint {
|
||||
|
||||
@@ -6,7 +6,6 @@ import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.InputType
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
@@ -40,7 +39,10 @@ private val downloadsResourcePatch = resourcePatch {
|
||||
preferences = setOf(
|
||||
SwitchPreference("revanced_external_downloader"),
|
||||
SwitchPreference("revanced_external_downloader_action_button"),
|
||||
TextPreference("revanced_external_downloader_name", inputType = InputType.TEXT),
|
||||
TextPreference(
|
||||
"revanced_external_downloader_name",
|
||||
tag = "app.revanced.extension.youtube.settings.preference.ExternalDownloaderPreference",
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -201,9 +201,9 @@ val hideLayoutComponentsPatch = bytecodePatch(
|
||||
key = "revanced_hide_filter_bar_screen",
|
||||
preferences = setOf(
|
||||
SwitchPreference("revanced_hide_filter_bar_feed_in_feed"),
|
||||
SwitchPreference("revanced_hide_filter_bar_feed_in_history"),
|
||||
SwitchPreference("revanced_hide_filter_bar_feed_in_search"),
|
||||
SwitchPreference("revanced_hide_filter_bar_feed_in_related_videos"),
|
||||
SwitchPreference("revanced_hide_filter_bar_feed_in_search"),
|
||||
SwitchPreference("revanced_hide_filter_bar_feed_in_history"),
|
||||
),
|
||||
),
|
||||
PreferenceScreenPreference(
|
||||
@@ -223,7 +223,6 @@ val hideLayoutComponentsPatch = bytecodePatch(
|
||||
SwitchPreference("revanced_hide_crowdfunding_box"),
|
||||
SwitchPreference("revanced_hide_chips_shelf"),
|
||||
SwitchPreference("revanced_hide_expandable_card"),
|
||||
SwitchPreference("revanced_hide_feed_survey"),
|
||||
SwitchPreference("revanced_hide_floating_microphone_button"),
|
||||
SwitchPreference("revanced_hide_horizontal_shelves"),
|
||||
SwitchPreference("revanced_hide_image_shelf"),
|
||||
@@ -233,6 +232,7 @@ val hideLayoutComponentsPatch = bytecodePatch(
|
||||
SwitchPreference("revanced_hide_notify_me_button"),
|
||||
SwitchPreference("revanced_hide_playables"),
|
||||
SwitchPreference("revanced_hide_show_more_button"),
|
||||
SwitchPreference("revanced_hide_surveys"),
|
||||
SwitchPreference("revanced_hide_ticket_shelf"),
|
||||
SwitchPreference("revanced_hide_video_recommendation_labels"),
|
||||
SwitchPreference("revanced_hide_doodles"),
|
||||
|
||||
@@ -99,7 +99,7 @@ val hideInfoCardsPatch = bytecodePatch(
|
||||
)
|
||||
|
||||
// Info cards can also appear as Litho components.
|
||||
val filterClassDescriptor = "Lapp/revanced/extension/youtube/patches/components/HideInfoCardsFilterPatch;"
|
||||
val filterClassDescriptor = "Lapp/revanced/extension/youtube/patches/components/HideInfoCardsFilter;"
|
||||
addLithoFilter(filterClassDescriptor)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,8 +66,8 @@ private val hideShortsComponentsResourcePatch = resourcePatch {
|
||||
|
||||
PreferenceScreen.SHORTS.addPreferences(
|
||||
SwitchPreference("revanced_hide_shorts_home"),
|
||||
SwitchPreference("revanced_hide_shorts_subscriptions"),
|
||||
SwitchPreference("revanced_hide_shorts_search"),
|
||||
SwitchPreference("revanced_hide_shorts_subscriptions"),
|
||||
SwitchPreference("revanced_hide_shorts_history"),
|
||||
|
||||
PreferenceScreenPreference(
|
||||
|
||||
@@ -43,7 +43,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/ReturnYouTubeDislikePatch;"
|
||||
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilterPatch;"
|
||||
"Lapp/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilter;"
|
||||
|
||||
val returnYouTubeDislikePatch = bytecodePatch(
|
||||
name = "Return YouTube Dislike",
|
||||
|
||||
@@ -156,7 +156,7 @@ val lithoFilterPatch = bytecodePatch(
|
||||
move-object/from16 v$freeRegister, p2
|
||||
iget-object v$identifierRegister, v$freeRegister, $conversionContextIdentifierField
|
||||
iget-object v$pathRegister, v$freeRegister, $conversionContextPathBuilderField
|
||||
invoke-static { v$identifierRegister, v$pathRegister }, $EXTENSION_CLASS_DESCRIPTOR->shouldFilter(Ljava/lang/String;Ljava/lang/StringBuilder;)Z
|
||||
invoke-static { v$identifierRegister, v$pathRegister }, $EXTENSION_CLASS_DESCRIPTOR->isFiltered(Ljava/lang/String;Ljava/lang/StringBuilder;)Z
|
||||
move-result v$freeRegister
|
||||
if-eqz v$freeRegister, :unfiltered
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ val recyclerViewTreeHookPatch = bytecodePatch {
|
||||
dependsOn(sharedExtensionPatch)
|
||||
|
||||
execute {
|
||||
|
||||
recyclerViewTreeObserverFingerprint.method.apply {
|
||||
val insertIndex = recyclerViewTreeObserverFingerprint.patternMatch!!.startIndex + 1
|
||||
val recyclerViewParameter = 2
|
||||
|
||||
@@ -12,31 +12,15 @@ import app.revanced.patches.shared.misc.mapping.get
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||
import app.revanced.patches.shared.misc.settings.overrideThemeColors
|
||||
import app.revanced.patches.shared.misc.settings.preference.BasePreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.BasePreferenceScreen
|
||||
import app.revanced.patches.shared.misc.settings.preference.InputType
|
||||
import app.revanced.patches.shared.misc.settings.preference.IntentPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.ListPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceCategory
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.*
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
||||
import app.revanced.patches.shared.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.misc.check.checkEnvironmentPatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.fix.playbackspeed.fixPlaybackSpeedWhilePlayingPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.addInstructionsAtControlFlowLabel
|
||||
import app.revanced.util.copyResources
|
||||
import app.revanced.util.copyXmlNode
|
||||
import app.revanced.util.findElementByAttributeValueOrThrow
|
||||
import app.revanced.util.findInstructionIndicesReversedOrThrow
|
||||
import app.revanced.util.inputStreamFromBundledResource
|
||||
import app.revanced.util.insertLiteralOverride
|
||||
import app.revanced.util.*
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
||||
@@ -152,15 +136,24 @@ private val settingsResourcePatch = resourcePatch {
|
||||
}
|
||||
}
|
||||
|
||||
// Modify the manifest and add a data intent filter to the LicenseActivity.
|
||||
// Some devices freak out if undeclared data is passed to an intent,
|
||||
// and this change appears to fix the issue.
|
||||
// Modify the manifest to enhance LicenseActivity behavior:
|
||||
// 1. Add a data intent filter with MIME type "text/plain".
|
||||
// Some devices crash if undeclared data is passed to an intent,
|
||||
// and this change appears to fix the issue.
|
||||
// 2. Add android:configChanges="orientation|screenSize|keyboardHidden".
|
||||
// This prevents the activity from being recreated on configuration changes
|
||||
// (e.g., screen rotation), preserving its current state and fragment.
|
||||
document("AndroidManifest.xml").use { document ->
|
||||
val licenseElement = document.childNodes.findElementByAttributeValueOrThrow(
|
||||
"android:name",
|
||||
"com.google.android.libraries.social.licenses.LicenseActivity",
|
||||
)
|
||||
|
||||
licenseElement.setAttribute(
|
||||
"android:configChanges",
|
||||
"orientation|screenSize|keyboardHidden"
|
||||
)
|
||||
|
||||
val mimeType = document.createElement("data")
|
||||
mimeType.setAttribute("android:mimeType", "text/plain")
|
||||
|
||||
@@ -242,9 +235,9 @@ val settingsPatch = bytecodePatch(
|
||||
methods.removeIf { it.name != "onCreate" && !MethodUtil.isConstructor(it) }
|
||||
}
|
||||
|
||||
// Add context override to force a specific settings language.
|
||||
licenseActivityOnCreateFingerprint.classDef.apply {
|
||||
val attachBaseContext = ImmutableMethod(
|
||||
// Add attachBaseContext method to override the context for setting a specific language.
|
||||
ImmutableMethod(
|
||||
type,
|
||||
"attachBaseContext",
|
||||
listOf(ImmutableMethodParameter("Landroid/content/Context;", null, null)),
|
||||
@@ -262,9 +255,50 @@ val settingsPatch = bytecodePatch(
|
||||
return-void
|
||||
"""
|
||||
)
|
||||
}
|
||||
}.let(methods::add)
|
||||
|
||||
methods.add(attachBaseContext)
|
||||
// Add onBackPressed method to handle back button presses, delegating to SearchViewController.
|
||||
ImmutableMethod(
|
||||
type,
|
||||
"onBackPressed",
|
||||
emptyList(),
|
||||
"V",
|
||||
AccessFlags.PUBLIC.value,
|
||||
null,
|
||||
null,
|
||||
MutableMethodImplementation(3),
|
||||
).toMutable().apply {
|
||||
addInstructions(
|
||||
"""
|
||||
invoke-static {}, Lapp/revanced/extension/youtube/settings/SearchViewController;->handleBackPress()Z
|
||||
move-result v0
|
||||
if-nez v0, :search_handled
|
||||
invoke-virtual { p0 }, Landroid/app/Activity;->finish()V
|
||||
:search_handled
|
||||
return-void
|
||||
"""
|
||||
)
|
||||
}.let(methods::add)
|
||||
|
||||
// Add onConfigurationChanged method to handle configuration changes (e.g., screen orientation).
|
||||
ImmutableMethod(
|
||||
type,
|
||||
"onConfigurationChanged",
|
||||
listOf(ImmutableMethodParameter("Landroid/content/res/Configuration;", null, null)),
|
||||
"V",
|
||||
AccessFlags.PUBLIC.value,
|
||||
null,
|
||||
null,
|
||||
MutableMethodImplementation(3)
|
||||
).toMutable().apply {
|
||||
addInstructions(
|
||||
"""
|
||||
invoke-super { p0, p1 }, Landroid/app/Activity;->onConfigurationChanged(Landroid/content/res/Configuration;)V
|
||||
invoke-static { p0, p1 }, $EXTENSION_CLASS_DESCRIPTOR->handleConfigurationChanged(Landroid/app/Activity;Landroid/content/res/Configuration;)V
|
||||
return-void
|
||||
"""
|
||||
)
|
||||
}.let(methods::add)
|
||||
}
|
||||
|
||||
// Update shared dark mode status based on YT theme.
|
||||
@@ -338,20 +372,18 @@ object PreferenceScreen : BasePreferenceScreen() {
|
||||
icon = "@drawable/revanced_settings_screen_05_player",
|
||||
layout = "@layout/preference_with_icon",
|
||||
)
|
||||
|
||||
val SHORTS = Screen(
|
||||
key = "revanced_settings_screen_06_shorts",
|
||||
summaryKey = null,
|
||||
icon = "@drawable/revanced_settings_screen_06_shorts",
|
||||
layout = "@layout/preference_with_icon",
|
||||
)
|
||||
|
||||
val SEEKBAR = Screen(
|
||||
key = "revanced_settings_screen_07_seekbar",
|
||||
summaryKey = null,
|
||||
icon = "@drawable/revanced_settings_screen_07_seekbar",
|
||||
layout = "@layout/preference_with_icon",
|
||||
)
|
||||
)
|
||||
val SWIPE_CONTROLS = Screen(
|
||||
key = "revanced_settings_screen_08_swipe_controls",
|
||||
summaryKey = null,
|
||||
|
||||
@@ -121,7 +121,7 @@ internal val subtitleButtonControllerFingerprint = fingerprint {
|
||||
)
|
||||
}
|
||||
|
||||
internal val newVideoQualityChangedFingerprint = fingerprint {
|
||||
internal val videoQualityChangedFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("L")
|
||||
parameters("L")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patches.youtube.video.information
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patches.youtube.shared.newVideoQualityChangedFingerprint
|
||||
import app.revanced.patches.youtube.shared.videoQualityChangedFingerprint
|
||||
import app.revanced.util.getReference
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
@@ -110,7 +110,7 @@ internal val seekRelativeFingerprint = fingerprint {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves with the class found in [newVideoQualityChangedFingerprint].
|
||||
* Resolves with the class found in [videoQualityChangedFingerprint].
|
||||
*/
|
||||
internal val playbackSpeedMenuSpeedChangedFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
|
||||
@@ -9,7 +9,7 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patcher.util.smali.toInstructions
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.shared.newVideoQualityChangedFingerprint
|
||||
import app.revanced.patches.youtube.shared.videoQualityChangedFingerprint
|
||||
import app.revanced.patches.youtube.video.playerresponse.Hook
|
||||
import app.revanced.patches.youtube.video.playerresponse.addPlayerResponseMethodHook
|
||||
import app.revanced.patches.youtube.video.playerresponse.playerResponseMethodHookPatch
|
||||
@@ -263,7 +263,7 @@ val videoInformationPatch = bytecodePatch(
|
||||
|
||||
// Handle new playback speed menu.
|
||||
playbackSpeedMenuSpeedChangedFingerprint.match(
|
||||
newVideoQualityChangedFingerprint.originalClassDef,
|
||||
videoQualityChangedFingerprint.originalClassDef,
|
||||
).method.apply {
|
||||
val index = indexOfFirstInstructionOrThrow(Opcode.IGET)
|
||||
|
||||
|
||||
@@ -68,7 +68,6 @@ internal val advancedVideoQualityMenuPatch = bytecodePatch {
|
||||
// region Patch for the old type of the video quality menu.
|
||||
// Used for regular videos when spoofing to old app version,
|
||||
// and for the Shorts quality flyout on newer app versions.
|
||||
|
||||
videoQualityMenuViewInflateFingerprint.let {
|
||||
it.method.apply {
|
||||
val checkCastIndex = it.patternMatch!!.endIndex
|
||||
@@ -77,7 +76,7 @@ internal val advancedVideoQualityMenuPatch = bytecodePatch {
|
||||
addInstruction(
|
||||
checkCastIndex + 1,
|
||||
"invoke-static { v$listViewRegister }, $EXTENSION_CLASS_DESCRIPTOR->" +
|
||||
"showAdvancedVideoQualityMenu(Landroid/widget/ListView;)V",
|
||||
"addVideoQualityListMenuListener(Landroid/widget/ListView;)V",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,25 @@ import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
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 setQualityByIndexMethodClassFieldReferenceFingerprint = fingerprint {
|
||||
internal val setVideoQualityFingerprint = fingerprint {
|
||||
returns("V")
|
||||
parameters("L")
|
||||
opcodes(
|
||||
@@ -23,6 +38,22 @@ internal val videoQualityItemOnClickParentFingerprint = fingerprint {
|
||||
strings("VIDEO_QUALITIES_MENU_BOTTOM_SHEET_FRAGMENT")
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves to class found in [videoQualityItemOnClickFingerprint].
|
||||
*/
|
||||
internal val videoQualityItemOnClickFingerprint = fingerprint {
|
||||
returns("V")
|
||||
parameters(
|
||||
"Landroid/widget/AdapterView;",
|
||||
"Landroid/view/View;",
|
||||
"I",
|
||||
"J"
|
||||
)
|
||||
custom { method, _ ->
|
||||
method.name == "onItemClick"
|
||||
}
|
||||
}
|
||||
|
||||
internal val videoQualitySetterFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
@@ -37,7 +68,6 @@ internal val videoQualitySetterFingerprint = fingerprint {
|
||||
strings("menu_item_video_quality")
|
||||
}
|
||||
|
||||
|
||||
internal val videoQualityMenuOptionsFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.STATIC)
|
||||
returns("[L")
|
||||
|
||||
@@ -3,8 +3,8 @@ package app.revanced.patches.youtube.video.quality
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
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.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.ListPreference
|
||||
@@ -12,15 +12,21 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.shared.newVideoQualityChangedFingerprint
|
||||
import app.revanced.patches.youtube.shared.videoQualityChangedFingerprint
|
||||
import app.revanced.patches.youtube.video.information.onCreateHook
|
||||
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.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch;"
|
||||
private const val EXTENSION_VIDEO_QUALITY_MENU_INTERFACE =
|
||||
"Lapp/revanced/extension/youtube/patches/playback/quality/RememberVideoQualityPatch\$VideoQualityMenuInterface;"
|
||||
|
||||
val rememberVideoQualityPatch = bytecodePatch {
|
||||
dependsOn(
|
||||
@@ -61,81 +67,152 @@ val rememberVideoQualityPatch = bytecodePatch {
|
||||
SwitchPreference("revanced_remember_video_quality_last_selected_toast")
|
||||
))
|
||||
|
||||
/*
|
||||
* The following code works by hooking the method which is called when the user selects a video quality
|
||||
* to remember the last selected video quality.
|
||||
*
|
||||
* It also hooks the method which is called when the video quality to set is determined.
|
||||
* Conveniently, at this point the video quality is overridden to the remembered playback speed.
|
||||
*/
|
||||
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.
|
||||
setQualityByIndexMethodClassFieldReferenceFingerprint.match(
|
||||
videoQualitySetterFingerprint.originalClassDef,
|
||||
setVideoQualityFingerprint.match(
|
||||
videoQualitySetterFingerprint.originalClassDef
|
||||
).let { match ->
|
||||
// This instruction refers to the field with the type that contains the setQualityByIndex method.
|
||||
// This instruction refers to the field with the type that contains the setQuality method.
|
||||
val instructions = match.method.implementation!!.instructions
|
||||
|
||||
val getOnItemClickListenerClassReference =
|
||||
val onItemClickListenerClassReference =
|
||||
(instructions.elementAt(0) as ReferenceInstruction).reference
|
||||
val getSetQualityByIndexMethodClassFieldReference =
|
||||
(instructions.elementAt(1) as ReferenceInstruction).reference
|
||||
val setQualityFieldReference =
|
||||
((instructions.elementAt(1) as ReferenceInstruction).reference) as FieldReference
|
||||
|
||||
val setQualityByIndexMethodClassFieldReference =
|
||||
getSetQualityByIndexMethodClassFieldReference 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)
|
||||
|
||||
val setQualityByIndexMethodClass = classes
|
||||
.find { classDef -> classDef.type == setQualityByIndexMethodClassFieldReference.type }!!
|
||||
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
|
||||
}
|
||||
|
||||
// Get the name of the setQualityByIndex method.
|
||||
val setQualityByIndexMethod = setQualityByIndexMethodClass.methods
|
||||
.find { method -> method.parameterTypes.first() == "I" }
|
||||
?: throw PatchException("Could not find setQualityByIndex method")
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-virtual { p0, p1 }, $setQualityMenuIndexMethod
|
||||
return-void
|
||||
"""
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
videoQualitySetterFingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
# Get the object instance to invoke the setQualityByIndex method on.
|
||||
iget-object v0, p0, $getOnItemClickListenerClassReference
|
||||
iget-object v0, v0, $getSetQualityByIndexMethodClassFieldReference
|
||||
# Get object instance to invoke setQuality method.
|
||||
iget-object v0, p0, $onItemClickListenerClassReference
|
||||
iget-object v0, v0, $setQualityFieldReference
|
||||
|
||||
# Get the method name.
|
||||
const-string v1, "${setQualityByIndexMethod.name}"
|
||||
|
||||
# Set the quality.
|
||||
# The first parameter is the array list of video qualities.
|
||||
# The second parameter is the index of the selected quality.
|
||||
# The register v0 stores the object instance to invoke the setQualityByIndex method on.
|
||||
# The register v1 stores the name of the setQualityByIndex method.
|
||||
invoke-static { p1, p2, v0, v1 }, $EXTENSION_CLASS_DESCRIPTOR->setVideoQuality([Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/String;)I
|
||||
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.
|
||||
videoQualityItemOnClickParentFingerprint.classDef.methods.find { it.name == "onItemClick" }
|
||||
?.apply {
|
||||
val listItemIndexParameter = 3
|
||||
// Inject a call to remember the selected quality for Shorts.
|
||||
videoQualityItemOnClickFingerprint.match(
|
||||
videoQualityItemOnClickParentFingerprint.classDef
|
||||
).method.addInstruction(
|
||||
0,
|
||||
"invoke-static { p3 }, $EXTENSION_CLASS_DESCRIPTOR->userChangedShortsQuality(I)V"
|
||||
)
|
||||
|
||||
// Inject a call to remember the user selected quality for regular videos.
|
||||
videoQualityChangedFingerprint.let {
|
||||
it.method.apply {
|
||||
val index = it.patternMatch!!.startIndex
|
||||
val register = getInstruction<TwoRegisterInstruction>(index).registerA
|
||||
|
||||
addInstruction(
|
||||
0,
|
||||
"invoke-static { p$listItemIndexParameter }, " +
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->userChangedQuality(I)V",
|
||||
index + 1,
|
||||
"invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->userChangedQuality(I)V",
|
||||
)
|
||||
} ?: throw PatchException("Failed to find onItemClick method")
|
||||
|
||||
// Remember video quality if not using old layout menu.
|
||||
newVideoQualityChangedFingerprint.method.apply {
|
||||
val index = newVideoQualityChangedFingerprint.patternMatch!!.startIndex
|
||||
val qualityRegister = getInstruction<TwoRegisterInstruction>(index).registerA
|
||||
|
||||
addInstruction(
|
||||
index + 1,
|
||||
"invoke-static { v$qualityRegister }, " +
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->userChangedQualityInNewFlyout(I)V",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ 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.PreferenceScreenPreference.Sorting
|
||||
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.
|
||||
@@ -19,6 +20,7 @@ val videoQualityPatch = bytecodePatch(
|
||||
dependsOn(
|
||||
rememberVideoQualityPatch,
|
||||
advancedVideoQualityMenuPatch,
|
||||
videoQualityButtonPatch,
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package app.revanced.patches.youtube.video.quality.button
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playercontrols.*
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
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.copyResources
|
||||
|
||||
private val videoQualityButtonResourcePatch = resourcePatch {
|
||||
dependsOn(playerControlsResourcePatch)
|
||||
|
||||
execute {
|
||||
copyResources(
|
||||
"qualitybutton",
|
||||
ResourceGroup(
|
||||
"drawable",
|
||||
"revanced_video_quality_dialog_button_ld.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",
|
||||
),
|
||||
)
|
||||
|
||||
addBottomControl("qualitybutton")
|
||||
}
|
||||
}
|
||||
|
||||
private const val QUALITY_BUTTON_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/videoplayer/VideoQualityDialogButton;"
|
||||
|
||||
val videoQualityButtonPatch = bytecodePatch(
|
||||
description = "Adds the option to display video quality dialog button in the video player.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
rememberVideoQualityPatch,
|
||||
videoQualityButtonResourcePatch,
|
||||
playerControlsPatch,
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("youtube", "video.quality.button.videoQualityButtonPatch")
|
||||
|
||||
PreferenceScreen.PLAYER.addPreferences(
|
||||
SwitchPreference("revanced_video_quality_dialog_button"),
|
||||
)
|
||||
|
||||
initializeBottomControl(QUALITY_BUTTON_CLASS_DESCRIPTOR)
|
||||
injectVisibilityCheckCall(QUALITY_BUTTON_CLASS_DESCRIPTOR)
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,19 @@
|
||||
package app.revanced.patches.youtube.video.speed.custom
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.mapping.get
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||
import app.revanced.patches.shared.misc.settings.preference.InputType
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
||||
@@ -18,18 +26,34 @@ import app.revanced.patches.youtube.misc.recyclerviewtree.hook.addRecyclerViewTr
|
||||
import app.revanced.patches.youtube.misc.recyclerviewtree.hook.recyclerViewTreeHookPatch
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.video.speed.settingsMenuVideoSpeedGroup
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.indexOfFirstLiteralInstruction
|
||||
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableField
|
||||
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilterPatch;"
|
||||
"Lapp/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilter;"
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
internal const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch;"
|
||||
|
||||
internal var speedUnavailableId = -1L
|
||||
private set
|
||||
|
||||
private val customPlaybackSpeedResourcePatch = resourcePatch {
|
||||
dependsOn(resourceMappingPatch)
|
||||
|
||||
execute {
|
||||
speedUnavailableId = resourceMappings["string", "varispeed_unavailable_message"]
|
||||
}
|
||||
}
|
||||
|
||||
internal val customPlaybackSpeedPatch = bytecodePatch(
|
||||
description = "Adds custom playback speed options.",
|
||||
) {
|
||||
@@ -39,7 +63,8 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
|
||||
addResourcesPatch,
|
||||
lithoFilterPatch,
|
||||
versionCheckPatch,
|
||||
recyclerViewTreeHookPatch
|
||||
recyclerViewTreeHookPatch,
|
||||
customPlaybackSpeedResourcePatch
|
||||
)
|
||||
|
||||
execute {
|
||||
@@ -48,6 +73,7 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
|
||||
settingsMenuVideoSpeedGroup.addAll(
|
||||
listOf(
|
||||
SwitchPreference("revanced_custom_speed_menu"),
|
||||
SwitchPreference("revanced_restore_old_speed_menu"),
|
||||
TextPreference(
|
||||
"revanced_custom_playback_speeds",
|
||||
inputType = InputType.TEXT_MULTI_LINE
|
||||
@@ -77,15 +103,88 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
|
||||
replaceInstruction(limitMaxIndex, "const/high16 v$limitMaxRegister, 8.0f")
|
||||
}
|
||||
|
||||
|
||||
// Replace the speeds float array with custom speeds.
|
||||
// These speeds are used if the speed menu is immediately opened after a video is opened.
|
||||
speedArrayGeneratorFingerprint.method.apply {
|
||||
val sizeCallIndex = indexOfFirstInstructionOrThrow { getReference<MethodReference>()?.name == "size" }
|
||||
val sizeCallResultRegister = getInstruction<OneRegisterInstruction>(sizeCallIndex + 1).registerA
|
||||
|
||||
replaceInstruction(sizeCallIndex + 1, "const/4 v$sizeCallResultRegister, 0x0")
|
||||
|
||||
val arrayLengthConstIndex = indexOfFirstLiteralInstructionOrThrow(7)
|
||||
val arrayLengthConstDestination = getInstruction<OneRegisterInstruction>(arrayLengthConstIndex).registerA
|
||||
val playbackSpeedsArrayType = "$EXTENSION_CLASS_DESCRIPTOR->customPlaybackSpeeds:[F"
|
||||
|
||||
addInstructions(
|
||||
arrayLengthConstIndex + 1,
|
||||
"""
|
||||
sget-object v$arrayLengthConstDestination, $playbackSpeedsArrayType
|
||||
array-length v$arrayLengthConstDestination, v$arrayLengthConstDestination
|
||||
""",
|
||||
)
|
||||
|
||||
val originalArrayFetchIndex = indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<FieldReference>()
|
||||
reference?.type == "[F" && reference.definingClass.endsWith("/PlayerConfigModel;")
|
||||
}
|
||||
val originalArrayFetchDestination =
|
||||
getInstruction<OneRegisterInstruction>(originalArrayFetchIndex).registerA
|
||||
|
||||
replaceInstruction(
|
||||
originalArrayFetchIndex,
|
||||
"sget-object v$originalArrayFetchDestination, $playbackSpeedsArrayType",
|
||||
)
|
||||
}
|
||||
|
||||
// region Force old video quality menu.
|
||||
|
||||
// Add a static INSTANCE field to the class.
|
||||
// This is later used to call "showOldPlaybackSpeedMenu" on the instance.
|
||||
|
||||
val instanceField = ImmutableField(
|
||||
getOldPlaybackSpeedsFingerprint.originalClassDef.type,
|
||||
"INSTANCE",
|
||||
getOldPlaybackSpeedsFingerprint.originalClassDef.type,
|
||||
AccessFlags.PUBLIC.value or AccessFlags.STATIC.value,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
).toMutable()
|
||||
|
||||
getOldPlaybackSpeedsFingerprint.classDef.staticFields.add(instanceField)
|
||||
// Set the INSTANCE field to the instance of the class.
|
||||
// In order to prevent a conflict with another patch, add the instruction at index 1.
|
||||
getOldPlaybackSpeedsFingerprint.method.addInstruction(1, "sput-object p0, $instanceField")
|
||||
|
||||
// Get the "showOldPlaybackSpeedMenu" method.
|
||||
// This is later called on the field INSTANCE.
|
||||
val showOldPlaybackSpeedMenuMethod = showOldPlaybackSpeedMenuFingerprint.match(
|
||||
getOldPlaybackSpeedsFingerprint.classDef,
|
||||
).method
|
||||
|
||||
// Insert the call to the "showOldPlaybackSpeedMenu" method on the field INSTANCE.
|
||||
showOldPlaybackSpeedMenuExtensionFingerprint.method.apply {
|
||||
addInstructionsWithLabels(
|
||||
instructions.lastIndex,
|
||||
"""
|
||||
sget-object v0, $instanceField
|
||||
if-nez v0, :not_null
|
||||
return-void
|
||||
:not_null
|
||||
invoke-virtual { v0 }, $showOldPlaybackSpeedMenuMethod
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// Close the unpatched playback dialog and show the modern custom dialog.
|
||||
addRecyclerViewTreeHook(EXTENSION_CLASS_DESCRIPTOR)
|
||||
|
||||
// Required to check if the playback speed menu is currently shown.
|
||||
addLithoFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
// endregion
|
||||
|
||||
|
||||
// region Custom tap and hold 2x speed.
|
||||
|
||||
if (is_19_25_or_greater) {
|
||||
|
||||
@@ -3,10 +3,33 @@ package app.revanced.patches.youtube.video.speed.custom
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.reference.StringReference
|
||||
|
||||
internal val getOldPlaybackSpeedsFingerprint = fingerprint {
|
||||
parameters("[L", "I")
|
||||
strings("menu_item_playback_speed")
|
||||
}
|
||||
|
||||
internal val showOldPlaybackSpeedMenuFingerprint = fingerprint {
|
||||
literal { speedUnavailableId }
|
||||
}
|
||||
|
||||
internal val showOldPlaybackSpeedMenuExtensionFingerprint = fingerprint {
|
||||
custom { method, classDef ->
|
||||
method.name == "showOldPlaybackSpeedMenu" && classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
||||
}
|
||||
}
|
||||
|
||||
internal val speedArrayGeneratorFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returns("[L")
|
||||
parameters("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;")
|
||||
strings("0.0#")
|
||||
}
|
||||
|
||||
internal val speedLimiterFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
|
||||
@@ -40,7 +40,7 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.general.hideLayoutComponentsPatch">
|
||||
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
|
||||
This item appear in the subscription feed for future livestreams or unreleased videos. -->
|
||||
This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
|
||||
<!-- 'Show more' should be translated with the same localized wording that YouTube displays.
|
||||
This button usually appears when searching for a YT creator. -->
|
||||
<!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. -->
|
||||
@@ -58,7 +58,6 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="ad.general.hideAdsResourcePatch">
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
|
||||
</patch>
|
||||
<patch id="ad.getpremium.hideGetPremiumPatch">
|
||||
</patch>
|
||||
@@ -68,7 +67,7 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="interaction.dialog.removeViewerDiscretionDialogPatch">
|
||||
</patch>
|
||||
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch">
|
||||
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
|
||||
</patch>
|
||||
<patch id="interaction.downloads.downloadsResourcePatch">
|
||||
<!-- 'Download action button' should be translated using the same wording as the translation of 'revanced_hide_download_button_title'. -->
|
||||
@@ -128,6 +127,7 @@ Second \"item\" text"</string>
|
||||
<patch id="layout.hide.rollingnumber.disableRollingNumberAnimationPatch">
|
||||
</patch>
|
||||
<patch id="layout.hide.seekbar.hideSeekbarPatch">
|
||||
<!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
|
||||
</patch>
|
||||
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
|
||||
@@ -170,8 +170,6 @@ Second \"item\" text"</string>
|
||||
<patch id="layout.formfactor.changeFormFactorPatch">
|
||||
</patch>
|
||||
<patch id="layout.spoofappversion.spoofAppVersionPatch">
|
||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_spoof_app_version_title'.
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch. -->
|
||||
</patch>
|
||||
<patch id="layout.startpage.changeStartPagePatch">
|
||||
</patch>
|
||||
@@ -224,6 +222,8 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="video.speed.button.playbackSpeedButtonPatch">
|
||||
</patch>
|
||||
<patch id="video.quality.button.videoQualityButtonPatch">
|
||||
</patch>
|
||||
<patch id="video.speed.custom.customPlaybackSpeedPatch">
|
||||
</patch>
|
||||
<patch id="video.speed.remember.rememberPlaybackSpeedPatch">
|
||||
|
||||
@@ -40,7 +40,7 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.general.hideLayoutComponentsPatch">
|
||||
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
|
||||
This item appear in the subscription feed for future livestreams or unreleased videos. -->
|
||||
This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
|
||||
<!-- 'Show more' should be translated with the same localized wording that YouTube displays.
|
||||
This button usually appears when searching for a YT creator. -->
|
||||
<!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. -->
|
||||
@@ -58,7 +58,6 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="ad.general.hideAdsResourcePatch">
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
|
||||
</patch>
|
||||
<patch id="ad.getpremium.hideGetPremiumPatch">
|
||||
</patch>
|
||||
@@ -68,7 +67,7 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="interaction.dialog.removeViewerDiscretionDialogPatch">
|
||||
</patch>
|
||||
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch">
|
||||
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
|
||||
</patch>
|
||||
<patch id="interaction.downloads.downloadsResourcePatch">
|
||||
<!-- 'Download action button' should be translated using the same wording as the translation of 'revanced_hide_download_button_title'. -->
|
||||
@@ -128,6 +127,7 @@ Second \"item\" text"</string>
|
||||
<patch id="layout.hide.rollingnumber.disableRollingNumberAnimationPatch">
|
||||
</patch>
|
||||
<patch id="layout.hide.seekbar.hideSeekbarPatch">
|
||||
<!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
|
||||
</patch>
|
||||
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
|
||||
@@ -170,8 +170,6 @@ Second \"item\" text"</string>
|
||||
<patch id="layout.formfactor.changeFormFactorPatch">
|
||||
</patch>
|
||||
<patch id="layout.spoofappversion.spoofAppVersionPatch">
|
||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_spoof_app_version_title'.
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch. -->
|
||||
</patch>
|
||||
<patch id="layout.startpage.changeStartPagePatch">
|
||||
</patch>
|
||||
@@ -224,6 +222,8 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="video.speed.button.playbackSpeedButtonPatch">
|
||||
</patch>
|
||||
<patch id="video.quality.button.videoQualityButtonPatch">
|
||||
</patch>
|
||||
<patch id="video.speed.custom.customPlaybackSpeedPatch">
|
||||
</patch>
|
||||
<patch id="video.speed.remember.rememberPlaybackSpeedPatch">
|
||||
|
||||
@@ -137,7 +137,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_debug_logs_disabled">تم تعطيل تسجيلات تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_logs_none_found">لم يتم العثور على سجلات</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">تم نسخ السجلات</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">فشل تصدير السجلات: $s</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">فشل تصدير السجلات: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">مسح سجلات تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">يمسح جميع سجلات تصحيح أخطاء ReVanced المخزنة</string>
|
||||
<string name="revanced_debug_logs_clear_toast">تم مسح السجلات</string>
|
||||
@@ -164,9 +164,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_expandable_card_title">إخفاء البطاقة القابلة للتوسيع</string>
|
||||
<string name="revanced_hide_expandable_card_summary_on">البطاقة القابلة للتوسيع أسفل مقاطع الفيديو مخفية</string>
|
||||
<string name="revanced_hide_expandable_card_summary_off">البطاقة القابلة للتوسيع أسفل مقاطع الفيديو معروضة</string>
|
||||
<string name="revanced_hide_feed_survey_title">إخفاء الاستبيانات</string>
|
||||
<string name="revanced_hide_feed_survey_summary_on">تم إخفاء الاستبيانات</string>
|
||||
<string name="revanced_hide_feed_survey_summary_off">يتم عرض الاستبيانات</string>
|
||||
<string name="revanced_hide_floating_microphone_button_title">إخفاء زر الميكروفون العائم</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_on">زر الميكروفون العائم في البحث مخفي</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_off">يظهر زر الميكروفون العائم في البحث</string>
|
||||
@@ -192,7 +189,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_movies_section_summary_on">تم إخفاء قسم الأفلام</string>
|
||||
<string name="revanced_hide_movies_section_summary_off">يتم عرض قسم الأفلام</string>
|
||||
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
|
||||
This item appear in the subscription feed for future livestreams or unreleased videos. -->
|
||||
This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
|
||||
<string name="revanced_hide_notify_me_button_title">إخفاء زر \'تنبيهي\'</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_on">زر إشعاري مخفي</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_off">زر إشعاري معروض</string>
|
||||
@@ -204,6 +201,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_show_more_button_title">إخفاء زر \'عرض المزيد\'</string>
|
||||
<string name="revanced_hide_show_more_button_summary_on">زر إظهار المزيد في نتائج البحث مخفي</string>
|
||||
<string name="revanced_hide_show_more_button_summary_off">زر إظهار المزيد في نتائج البحث معروض</string>
|
||||
<string name="revanced_hide_surveys_title">إخفاء الاستبيانات</string>
|
||||
<string name="revanced_hide_surveys_summary_on">الاستطلاعات مخفية</string>
|
||||
<string name="revanced_hide_surveys_summary_off">الاستطلاعات معروضة</string>
|
||||
<string name="revanced_hide_ticket_shelf_title">إخفاء رف التذاكر</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_on">تم إخفاء رف التذاكر</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_off">يتم عرض رف التذاكر</string>
|
||||
@@ -251,8 +251,8 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_timed_reactions_summary_on">تم إخفاء ردود الفعل المؤقتة</string>
|
||||
<string name="revanced_hide_timed_reactions_summary_off">يتم عرض ردود الفعل المؤقتة</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_title">إخفاء \'ملخص الفيديو الذي تم إنشاؤه بواسطة الذكاء الاصطناعي\'</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">تم إخفاء قسم ملخص الفيديو</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">يتم عرض قسم ملخص الفيديو</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">قسم ملخص الفيديو الذي تم إنشاؤه بواسطة الذكاء الاصطناعي مخفي</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">قسم ملخص الفيديو الذي تم إنشاؤه بواسطة الذكاء الاصطناعي معروض</string>
|
||||
<string name="revanced_hide_ask_section_title">إخفاء \"Ask\"</string>
|
||||
<string name="revanced_hide_ask_section_summary_on">تم إخفاء قسم \"Ask\"</string>
|
||||
<string name="revanced_hide_ask_section_summary_off">يتم عرض قسم \"Ask\"</string>
|
||||
@@ -280,19 +280,19 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_description_components_screen_title">وصف الفيديو</string>
|
||||
<string name="revanced_hide_description_components_screen_summary">إخفاء أو عرض مكونات وصف الفيديو</string>
|
||||
<string name="revanced_hide_filter_bar_screen_title">شريط التصفية</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">إخفاء أو إظهار شريط الفلترة في الخلاصات، السجل، نتائج البحث، والفيديوهات ذات الصلة</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">إخفاء أو إظهار شريط الفلترة في الموجزات ومقاطع الفيديو ذات الصلة ونتائج البحث وسجل المشاهدة</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_title">إخفاء في الموجز</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_on">مخفي في الموجز</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_off">معروض في الموجز</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">إخفاء في السجل</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">مخفي في السجل</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">معروض في السجل</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">إخفاء في نتائج البحث</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">مخفي في نتائج البحث</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">يُعرض في نتائج البحث</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">إخفاء في الفيديوهات ذات الصلة</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">مخفي في الفيديوهات ذات الصلة</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">يُعرض في الفيديوهات ذات الصلة</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">إخفاء في نتائج البحث</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">مخفي في نتائج البحث</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">يُعرض في نتائج البحث</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">إخفاء في سجل المشاهدة</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">مخفي في سجل المشاهدة</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">معروض في سجل المشاهدة</string>
|
||||
<string name="revanced_channel_screen_title">صفحة القناة</string>
|
||||
<string name="revanced_channel_screen_summary">إخفاء أو إظهار مكونات صفحة القناة</string>
|
||||
<!-- 'For You' should be translated using the same localized wording YouTube displays. -->
|
||||
@@ -315,12 +315,12 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_visit_store_button_summary_off">زر زيارة المتجر معروض</string>
|
||||
<string name="revanced_comments_screen_title">التعليقات</string>
|
||||
<string name="revanced_comments_screen_summary">إخفاء أو عرض مكونات قسم التعليقات</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_title">إخفاء ملخص محادثات الذكاء الاصطناعي</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">تم إخفاء ملخص المحادثات</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">يتم عرض ملخص المحادثات</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_title">إخفاء ملخص الدردشة بالذكاء الاصطناعي</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">ملخص الدردشة بالذكاء الاصطناعي مخفي</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">ملخص الدردشة بالذكاء الاصطناعي معروض</string>
|
||||
<string name="revanced_hide_comments_ai_summary_title">إخفاء ملخص تعليقات الذكاء الاصطناعي</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_on">تم إخفاء ملخص التعليقات</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_off">يتم عرض ملخص التعليقات</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_on">ملخص تعليقات الذكاء الاصطناعي مخفي</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_off">ملخص تعليقات الذكاء الاصطناعي معروض</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_title">إخفاء إرشادات القناة</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_on">إرشادات القناة مخفية</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_off">إرشادات القناة معروضة</string>
|
||||
@@ -419,7 +419,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_shopping_links_title">إخفاء روابط التسوق</string>
|
||||
<string name="revanced_hide_shopping_links_summary_on">روابط التسوق في وصف الفيديو مخفية</string>
|
||||
<string name="revanced_hide_shopping_links_summary_off">يتم عرض روابط التسوق في وصف الفيديو</string>
|
||||
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_view_products_banner_title">إخفاء لافتة \'عرض المنتجات\'</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_on">لافتة عرض المنتجات في تراكب الفيديو مخفية</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_off">لافتة عرض المنتجات في تراكب الفيديو معروضة</string>
|
||||
@@ -453,7 +452,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_summary_off">سيتم عرض مربع الحوار</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">وهذا لا يتجاوز قيود السن. بل يقبلها تلقائيًا.</string>
|
||||
</patch>
|
||||
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch">
|
||||
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
|
||||
<string name="revanced_disable_chapter_skip_double_tap_title">تعطيل تخطي الفصل بالنقر المزدوج</string>
|
||||
<string name="revanced_disable_chapter_skip_double_tap_summary_on">لا يمكن للنقر المزدوج مطلقًا أن يؤدي إلى تخطي الفصل التالي/السابق</string>
|
||||
<string name="revanced_disable_chapter_skip_double_tap_summary_off">يمكن للنقر المزدوج أن يؤدي أحيانًا إلى تخطي الفصل التالي/السابق</string>
|
||||
@@ -469,8 +468,15 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_on">يفتح زر التنزيل أداة التنزيل الخارجية</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_off">يفتح زر التنزيل أداة التنزيل الأصلية داخل التطبيق</string>
|
||||
<string name="revanced_external_downloader_name_title">اسم حزمة أداة التنزيل</string>
|
||||
<string name="revanced_external_downloader_name_summary">اسم الحزمة لتطبيق التنزيل الخارجي المثبت لديك، مثل NewPipe أو Seal</string>
|
||||
<string name="revanced_external_downloader_name_summary">اسم حزمة تطبيق التنزيل الخارجي المثبت لديك</string>
|
||||
<string name="revanced_external_downloader_other_item_hint">أدخل اسم الحزمة</string>
|
||||
<string name="revanced_external_downloader_other_item">أخرى</string>
|
||||
<string name="revanced_external_downloader_not_found_title">التطبيق غير مثبت</string>
|
||||
<string name="revanced_external_downloader_not_installed_warning">لم يتم تثبيت %s . الرجاء تثبيته.</string>
|
||||
<string name="revanced_external_downloader_package_not_found_warning">"تعذر العثور على التطبيق المثبت باسم الحزمة: %s
|
||||
|
||||
تأكد من أن اسم الحزمة صحيح وأن التطبيق مثبت"</string>
|
||||
<string name="revanced_external_downloader_empty_warning">لا يمكن أن يكون اسم الحزمة فارغًا</string>
|
||||
</patch>
|
||||
<patch id="interaction.seekbar.disablePreciseSeekingGesturePatch">
|
||||
<string name="revanced_disable_precise_seeking_gesture_title">تعطيل إيماءة التمرير الدقيقة</string>
|
||||
@@ -730,27 +736,28 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_disable_rolling_number_animations_summary_off">عدد مرات المشاهدة والإعجابات متحركة</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.seekbar.hideSeekbarPatch">
|
||||
<string name="revanced_hide_seekbar_title">إخفاء شريط التقدم في مشغل الفيديو</string>
|
||||
<string name="revanced_hide_seekbar_title">إخفاء شريط تقدم مشغل الفيديو</string>
|
||||
<string name="revanced_hide_seekbar_summary_on">تم إخفاء شريط تقدم الفيديو</string>
|
||||
<string name="revanced_hide_seekbar_summary_off">يتم عرض شريط تقدم الفيديو</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_title">إخفاء شريط التقدم في مُصَّغَرات الفيديو</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_on">تم إخفاء مصغرة شريط التقدم</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_off">يتم عرض مصغرة شريط التقدم</string>
|
||||
<!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
|
||||
<string name="revanced_hide_seekbar_thumbnail_title">إخفاء شريط تقدم صور مصغرة للفيديو</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_on">شريط تقدم صور مصغرة للفيديو مخفي</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_off">شريط تقدم صور مصغرة للفيديو معروض</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
|
||||
<string name="revanced_shorts_player_screen_title">مشغل Shorts</string>
|
||||
<string name="revanced_shorts_player_screen_summary">إخفاء أو عرض المكونات في مشغل Shorts</string>
|
||||
<string name="revanced_shorts_player_screen_summary">إخفاء أو إظهار مكونات مشغل Shorts</string>
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
|
||||
<string name="revanced_hide_shorts_home_title">إخفاء Shorts في الصفحة الرئيسية</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">مخفية في الصفحة الرئيسية ومقاطع الفيديو ذات الصلة</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">معروضة في الصفحة الرئيسية ومقاطع الفيديو ذات الصلة</string>
|
||||
<string name="revanced_hide_shorts_search_title">إخفاء Shorts في نتائج البحث</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">مخفية في نتائج البحث</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">تُعرض في نتائج البحث</string>
|
||||
<!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. -->
|
||||
<string name="revanced_hide_shorts_subscriptions_title">إخفاء Shorts في خلاصة الاشتراكات</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">مخفية في خلاصة الاشتراكات</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">معروضة في خلاصة الاشتراكات</string>
|
||||
<string name="revanced_hide_shorts_search_title">إخفاء Shorts في نتائج البحث</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">مخفية في نتائج البحث</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">تُعرض في نتائج البحث</string>
|
||||
<string name="revanced_hide_shorts_history_title">إخفاء Shorts في سجل المشاهدة</string>
|
||||
<string name="revanced_hide_shorts_history_summary_on">مخفية في سجل المشاهدة</string>
|
||||
<string name="revanced_hide_shorts_history_summary_off">تُعرض في سجل المشاهدة</string>
|
||||
@@ -1190,8 +1197,6 @@ Second \"item\" text"</string>
|
||||
سيؤدي هذا إلى تغيير مظهر ومميزات التطبيق، ولكن قد تحدث تأثيرات جانبية غير معروفة.
|
||||
|
||||
إذا تم إيقاف تشغيله لاحقًا، من المستحسن مسح بيانات التطبيق لمنع حدوث أخطاء في واجهة المستخدم."</string>
|
||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_spoof_app_version_title'.
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch. -->
|
||||
<string name="revanced_spoof_app_version_target_title">الهدف من تغيير إصدار التطبيق</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_1">19.35.36 - استعادة أيقونات مشغل Shorts القديمة</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_2">19.01.34 - استعادة أيقونات التنقل القديمة</string>
|
||||
@@ -1460,10 +1465,18 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_playback_speed_dialog_button_summary_on">الزر معروض. انقر مع الاستمرار لإعادة ضبط سرعة التشغيل إلى الوضع الافتراضي</string>
|
||||
<string name="revanced_playback_speed_dialog_button_summary_off">لا يتم عرض الزر</string>
|
||||
</patch>
|
||||
<patch id="video.quality.button.videoQualityButtonPatch">
|
||||
<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_off">الزر غير معروض</string>
|
||||
</patch>
|
||||
<patch id="video.speed.custom.customPlaybackSpeedPatch">
|
||||
<string name="revanced_custom_speed_menu_title">قائمة سرعة التشغيل المخصصة</string>
|
||||
<string name="revanced_custom_speed_menu_summary_on">يتم عرض قائمة سرعة التشغيل المخصصة</string>
|
||||
<string name="revanced_custom_speed_menu_summary_off">لا يتم عرض قائمة سرعة التشغيل المخصصة</string>
|
||||
<string name="revanced_restore_old_speed_menu_title">استعادة قائمة سرعة التشغيل القديمة</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_on">قائمة السرعة القديمة معروضة</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_off">قائمة السرعة الحديثة معروضة</string>
|
||||
<string name="revanced_custom_playback_speeds_title">سرعة التشغيل المخصصة</string>
|
||||
<string name="revanced_custom_playback_speeds_summary">إضافة أو تغيير سرعة التشغيل المخصصة</string>
|
||||
<string name="revanced_custom_playback_speeds_invalid">يجب أن تكون سرعات التشغيل المخصصة أقل من %s</string>
|
||||
|
||||
@@ -40,7 +40,7 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.general.hideLayoutComponentsPatch">
|
||||
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
|
||||
This item appear in the subscription feed for future livestreams or unreleased videos. -->
|
||||
This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
|
||||
<!-- 'Show more' should be translated with the same localized wording that YouTube displays.
|
||||
This button usually appears when searching for a YT creator. -->
|
||||
<!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. -->
|
||||
@@ -58,7 +58,6 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="ad.general.hideAdsResourcePatch">
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
|
||||
</patch>
|
||||
<patch id="ad.getpremium.hideGetPremiumPatch">
|
||||
</patch>
|
||||
@@ -68,7 +67,7 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="interaction.dialog.removeViewerDiscretionDialogPatch">
|
||||
</patch>
|
||||
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch">
|
||||
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
|
||||
</patch>
|
||||
<patch id="interaction.downloads.downloadsResourcePatch">
|
||||
<!-- 'Download action button' should be translated using the same wording as the translation of 'revanced_hide_download_button_title'. -->
|
||||
@@ -128,6 +127,7 @@ Second \"item\" text"</string>
|
||||
<patch id="layout.hide.rollingnumber.disableRollingNumberAnimationPatch">
|
||||
</patch>
|
||||
<patch id="layout.hide.seekbar.hideSeekbarPatch">
|
||||
<!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
|
||||
</patch>
|
||||
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
|
||||
@@ -170,8 +170,6 @@ Second \"item\" text"</string>
|
||||
<patch id="layout.formfactor.changeFormFactorPatch">
|
||||
</patch>
|
||||
<patch id="layout.spoofappversion.spoofAppVersionPatch">
|
||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_spoof_app_version_title'.
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch. -->
|
||||
</patch>
|
||||
<patch id="layout.startpage.changeStartPagePatch">
|
||||
</patch>
|
||||
@@ -226,6 +224,8 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="video.speed.button.playbackSpeedButtonPatch">
|
||||
</patch>
|
||||
<patch id="video.quality.button.videoQualityButtonPatch">
|
||||
</patch>
|
||||
<patch id="video.speed.custom.customPlaybackSpeedPatch">
|
||||
</patch>
|
||||
<patch id="video.speed.remember.rememberPlaybackSpeedPatch">
|
||||
|
||||
@@ -137,7 +137,7 @@ Gözlənilməz hallardan xəbərdar olmayacaqsınız."</string>
|
||||
<string name="revanced_debug_logs_disabled">Sazlama qeydi qapalıdır</string>
|
||||
<string name="revanced_debug_logs_none_found">Qeydlər tapılmadı</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Qeydlər köçürüldü</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Qeydləri ixrac etmək alınmadı: $s</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Qeydləri ixrac etmək alınmadı: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Sazlama qeydlərini təmizlə</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Saxlanılan bütün ReVanced sazlama qeydlərini təmizləyir</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Qeydlər silindi</string>
|
||||
@@ -164,9 +164,6 @@ Gözlənilməz hallardan xəbərdar olmayacaqsınız."</string>
|
||||
<string name="revanced_hide_expandable_card_title">Genişlənən kartı gizlət</string>
|
||||
<string name="revanced_hide_expandable_card_summary_on">Videoların aşağısında genişlənən kart gizlidir</string>
|
||||
<string name="revanced_hide_expandable_card_summary_off">Videoların altında genişlənən kart görünür</string>
|
||||
<string name="revanced_hide_feed_survey_title">Axın sorğuların gizlət</string>
|
||||
<string name="revanced_hide_feed_survey_summary_on">Axın sorğuları gizlidir</string>
|
||||
<string name="revanced_hide_feed_survey_summary_off">Axın sorğuları göstərilir</string>
|
||||
<string name="revanced_hide_floating_microphone_button_title">Üzən mikrofon düyməsini gizlət</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_on">Axtarışda üzən mikrofon düyməsi gizlidir</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_off">Üzən mikrofon düyməsi axtarışda göstərilir</string>
|
||||
@@ -192,7 +189,7 @@ Gözlənilməz hallardan xəbərdar olmayacaqsınız."</string>
|
||||
<string name="revanced_hide_movies_section_summary_on">Filmlər bölməsi gizlidir</string>
|
||||
<string name="revanced_hide_movies_section_summary_off">Filmlər bölməsi göstərilir</string>
|
||||
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
|
||||
This item appear in the subscription feed for future livestreams or unreleased videos. -->
|
||||
This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
|
||||
<string name="revanced_hide_notify_me_button_title">\"Mənə bildir\" düyməsini gizlət</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_on">Mənə bildir düyməsi gizlidir</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_off">Mənə bildir düyməsi görünür</string>
|
||||
@@ -204,6 +201,9 @@ Gözlənilməz hallardan xəbərdar olmayacaqsınız."</string>
|
||||
<string name="revanced_hide_show_more_button_title">\'Daha çox göstər\' düyməsini gizlət</string>
|
||||
<string name="revanced_hide_show_more_button_summary_on">Daha çox göstər düyməsi axtarış nəticələrində gizlidir</string>
|
||||
<string name="revanced_hide_show_more_button_summary_off">Daha çox göstər düyməsi axtarış nəticələrində görünür</string>
|
||||
<string name="revanced_hide_surveys_title">Sorğuları gizlət</string>
|
||||
<string name="revanced_hide_surveys_summary_on">Sorğular gizlədilib</string>
|
||||
<string name="revanced_hide_surveys_summary_off">Sorğular görünür</string>
|
||||
<string name="revanced_hide_ticket_shelf_title">Bilet bölməsin gizlət</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_on">Bilet bölməsi gizlidir</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_off">Bilet bölməsi görünür</string>
|
||||
@@ -251,8 +251,8 @@ Gözlənilməz hallardan xəbərdar olmayacaqsınız."</string>
|
||||
<string name="revanced_hide_timed_reactions_summary_on">Zamanlanmış reaksiyalar gizlədilir</string>
|
||||
<string name="revanced_hide_timed_reactions_summary_off">Zamanlanmış reaksiyalar göstərilir</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_title">\"AI ilə yaradılan video xülasəsini\" gizlət</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">Video xülasə bölməsi gizlədilib</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">Video xülasə bölməsi göstərilir</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">Sİ ilə yaradılan video xülasə bölməsi gizlədilib</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">Sİ ilə yaradılan video xülasə bölməsi görünür</string>
|
||||
<string name="revanced_hide_ask_section_title">Soruş\'u Gizlət</string>
|
||||
<string name="revanced_hide_ask_section_summary_on">Soruş bölməsi gizlidir</string>
|
||||
<string name="revanced_hide_ask_section_summary_off">\"Soruş\" bölməsi göstərilir</string>
|
||||
@@ -280,19 +280,19 @@ Gözlənilməz hallardan xəbərdar olmayacaqsınız."</string>
|
||||
<string name="revanced_hide_description_components_screen_title">Video təsviri</string>
|
||||
<string name="revanced_hide_description_components_screen_summary">Video təsviri elementlərini gizlət və ya göstər</string>
|
||||
<string name="revanced_hide_filter_bar_screen_title">Filtr çubuğu</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">Axınlar, tarixçə, axtarış nəticələri və əlaqəli videolarda filtr panelini gizlət və ya göstər</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">Axınlar, əlaqəli videolar, axtarış nəticələri və baxış tarixçəsində filtr cərgəsin gizlət və ya göstər</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_title">Axınlarda gizlət</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_on">Axınlarda gizlidir</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_off">Axınlarda göstər</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">Tarixçədə gizlət</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">Tarixçədə gizlədilib</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">Tarixçədə göstərilib</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">Axtarış nəticələrində gizlət</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">Axtarış nəticələrində gizlədilib</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">Axtarış nəticələrində göstərilir</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">Əlaqəli videolarda gizlət</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">Əlaqəli videolarda gizlidir</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">Əlaqəli videolarda görünür</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">Axtarış nəticələrində gizlət</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">Axtarış nəticələrində gizlədilib</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">Axtarış nəticələrində göstərilir</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">Baxış tarixçəsində gizlət</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">Baxış tarixçəsində gizlədilib</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">Baxış tarixçəsində görünür</string>
|
||||
<string name="revanced_channel_screen_title">Kanal səhifəsi</string>
|
||||
<string name="revanced_channel_screen_summary">Kanal səhifə elementlərini gizlət və ya göstər</string>
|
||||
<!-- 'For You' should be translated using the same localized wording YouTube displays. -->
|
||||
@@ -315,12 +315,12 @@ Gözlənilməz hallardan xəbərdar olmayacaqsınız."</string>
|
||||
<string name="revanced_hide_visit_store_button_summary_off">Mağazaya baxın düyməsi görünür</string>
|
||||
<string name="revanced_comments_screen_title">Şərhlər</string>
|
||||
<string name="revanced_comments_screen_summary">Şərhlər bölməsi elementlərin gizlət və ya göstər</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_title">AI Söhbət Xülasəsini Gizlət</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">Söhbət yekunu gizlidir </string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">Söhbət yekunu görünür</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_title">Sİ söhbət xülasəsini gizlət</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">Sİ söhbət xülasəsi gizlidir</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">Sİ söhbət xülasəsi görünür</string>
|
||||
<string name="revanced_hide_comments_ai_summary_title">AI Ṣərhlər Xülasəsini Gizlət</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_on">Ṣərh yekunu gizlidir </string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_off">Şərh yekunu görünür</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_on">Sİ şərhlər xülasəsi gizlidir</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_off">Sİ şərhlər xülasəsi görünür</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_title">Kanal təlimatlarını gizlət</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_on">Kanal təlimatları gizlidir</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_off">Kanal təlimatları görünür</string>
|
||||
@@ -419,7 +419,6 @@ Bu xüsusiyyət yalnız köhnə cihazlar üçün mövcuddur"</string>
|
||||
<string name="revanced_hide_shopping_links_title">Alış-veriş linklərini gizlət</string>
|
||||
<string name="revanced_hide_shopping_links_summary_on">Alış-veriş linkləri video təsvirdə gizlidir</string>
|
||||
<string name="revanced_hide_shopping_links_summary_off">Alış-veriş linkləri video təsvirdə görünür</string>
|
||||
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_view_products_banner_title">“Məhsullara baxın” panelin gizlət</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_on">Məhsullara baxış etiketi video örtüyündə gizlidir</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_off">Məhsullara baxış etiketi video örtüyündə görünür</string>
|
||||
@@ -453,7 +452,7 @@ Bu xüsusiyyət yalnız köhnə cihazlar üçün mövcuddur"</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_summary_off">Dialoq göstərilir</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">Bu, yaş məhdudiyyətini ötürmür. Sadəcə birbaşa qəbul edir.</string>
|
||||
</patch>
|
||||
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch">
|
||||
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
|
||||
<string name="revanced_disable_chapter_skip_double_tap_title">Cüt toxunuşla fəsil ötürməsini qapat</string>
|
||||
<string name="revanced_disable_chapter_skip_double_tap_summary_on">Cüt toxunma heç vaxt növbəti/əvvəlki fəsilə keçidi zorlaya bilməz</string>
|
||||
<string name="revanced_disable_chapter_skip_double_tap_summary_off">Cüt toxunma bəzən növbəti/əvvəlki fəsilə keçidi zorlaya bilər</string>
|
||||
@@ -469,8 +468,15 @@ Bu xüsusiyyət yalnız köhnə cihazlar üçün mövcuddur"</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_on">Yükləmə düyməsi, xarici yükləyicinizi açır</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_off">Yükləmə düyməsi tətbiqə xas yükləyicini açır</string>
|
||||
<string name="revanced_external_downloader_name_title">Yükləyici paketi adı</string>
|
||||
<string name="revanced_external_downloader_name_summary">NewPipe və ya Seal kimi quraşdırılan xarici yükləmə tətbiqinizin paket adı</string>
|
||||
<string name="revanced_external_downloader_name_summary">Quraşdırılan xarici yükləyici tətbiqinizin paket adı</string>
|
||||
<string name="revanced_external_downloader_other_item_hint">Paket adını yerləşdir</string>
|
||||
<string name="revanced_external_downloader_other_item">Digər</string>
|
||||
<string name="revanced_external_downloader_not_found_title">Tətbiq quraşdırılmayıb</string>
|
||||
<string name="revanced_external_downloader_not_installed_warning">%s quraşdırılmayıb. Lütfən, bunu quraşdır.</string>
|
||||
<string name="revanced_external_downloader_package_not_found_warning">"Paket adı ilə quraşdırılan tətbiq tapılmadı: %s
|
||||
|
||||
Paket adının düzgün olduğun yoxla və tətbiqi quraşdırın"</string>
|
||||
<string name="revanced_external_downloader_empty_warning">Paket adı boş ola bilməz</string>
|
||||
</patch>
|
||||
<patch id="interaction.seekbar.disablePreciseSeekingGesturePatch">
|
||||
<string name="revanced_disable_precise_seeking_gesture_title">Dəqiq axtarış jestini qapadın</string>
|
||||
@@ -730,27 +736,28 @@ Audio trek seçimin göstərmək üçün \"Video axınları saxtalaşdır\"ı iO
|
||||
<string name="revanced_disable_rolling_number_animations_summary_off">Sürüşən say animasiyası açıqdır</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.seekbar.hideSeekbarPatch">
|
||||
<string name="revanced_hide_seekbar_title">Video oynadıcıda irəliləyiş cizgisin gizlə</string>
|
||||
<string name="revanced_hide_seekbar_title">Video oynadıcı irəliləyiş cizgisin gizlət</string>
|
||||
<string name="revanced_hide_seekbar_summary_on">Video oynadıcı irəliləyiş cizgisi gizlidir</string>
|
||||
<string name="revanced_hide_seekbar_summary_off">Video oynadıcı irəliləyiş cizgisi göstərilir</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_title">Video miniatürdə irəliləmə cizgisin gizlə</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_on">Miniatür irəliləmə cizgisi gizlədilib</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_off">Miniatür irəliləmə cizgisi göstərilir</string>
|
||||
<!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
|
||||
<string name="revanced_hide_seekbar_thumbnail_title">Video miniatür irəliləyiş cizgisin gizlət</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_on">Video miniatür irəliləyiş cizgisi gizlidir</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_off">Video miniatür irəliləyiş cizgisi görünür</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
|
||||
<string name="revanced_shorts_player_screen_title">Shorts oynadıcı</string>
|
||||
<string name="revanced_shorts_player_screen_summary">Shorts oynadıcıda hissəcikləri gizlət və ya göstər</string>
|
||||
<string name="revanced_shorts_player_screen_summary">Shorts oynadıcı elementlərini gizlət və ya göstər</string>
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
|
||||
<string name="revanced_hide_shorts_home_title">Shorts-u Ev axınında gizlət</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">Ev axını və əlaqəli videolarda gizlidir</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">Ev axını və əlaqəli videolarda görünür</string>
|
||||
<string name="revanced_hide_shorts_search_title">Axtarış nəticələrindəki \"Shorts\"u gizlət</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">Axtarış nəticələrində gizlidir</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">Axtarış nəticələrində görünür</string>
|
||||
<!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. -->
|
||||
<string name="revanced_hide_shorts_subscriptions_title">Shorts-u Abunəliklər axınında gizlət</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">Abunəliklər axınında gizlidir</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">Abunəliklər axınında görünür</string>
|
||||
<string name="revanced_hide_shorts_search_title">Axtarış nəticələrindəki \"Shorts\"u gizlət</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">Axtarış nəticələrində gizlidir</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">Axtarış nəticələrində görünür</string>
|
||||
<string name="revanced_hide_shorts_history_title">Baxış tarixçəsində Shorts-u gizlət</string>
|
||||
<string name="revanced_hide_shorts_history_summary_on">Baxış tarixçəsində gizlidir</string>
|
||||
<string name="revanced_hide_shorts_history_summary_off">Baxış tarixçəsində göstərilib</string>
|
||||
@@ -1189,8 +1196,6 @@ Avtomobil tərtibatı
|
||||
Bu tətbiqin görünüşün və xüsusiyyətlərin dəyişdirəcək, lakin bilinməyən yan təsirlər ola bilər.
|
||||
|
||||
Sonradan qapadılarsa, UI səhvlərin önləmək üçün tətbiq məlumatların silmək tövsiyə olunur."</string>
|
||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_spoof_app_version_title'.
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch. -->
|
||||
<string name="revanced_spoof_app_version_target_title">Saxta tətbiq versiyası hədəfi</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_1">19.35.36 - Köhnə Shorts oynadıcı işarələrin bərpa et</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_2">19.01.34 - Köhnə fəaliyyət simvolların bərpa et</string>
|
||||
@@ -1459,10 +1464,15 @@ 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_off">Düymə göstərilmir</string>
|
||||
</patch>
|
||||
<patch id="video.quality.button.videoQualityButtonPatch">
|
||||
</patch>
|
||||
<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_summary_on">Fərdi sürət siyahısı göstərilir</string>
|
||||
<string name="revanced_custom_speed_menu_summary_off">Fərdi sürət siyahısı göstərilmir</string>
|
||||
<string name="revanced_restore_old_speed_menu_title">Köhnə oynatma sürəti menyusunu bərpa et</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_on">Köhnə sürət menyusu göstərilir</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_off">Müasir sürət menyusu göstərilir</string>
|
||||
<string name="revanced_custom_playback_speeds_title">Fərdi oynatma sürəti</string>
|
||||
<string name="revanced_custom_playback_speeds_summary">Fərdi oynatma sürətlərini əlavə et və ya dəyiş</string>
|
||||
<string name="revanced_custom_playback_speeds_invalid">Fərdi sürətlər %s dəyərindən az olmalıdır</string>
|
||||
|
||||
@@ -137,7 +137,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_debug_logs_disabled">Адладачнае лагаванне адключана</string>
|
||||
<string name="revanced_debug_logs_none_found">Лагі не знойдзены</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Лагі скапіяваны</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Не атрымалася экспартаваць лагі: $s</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Не ўдалося экспартаваць журналы: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Ачысціць адладачныя лагі</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Ачышчае ўсе захаваныя адладачныя лагі ReVanced</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Лагі ачышчаны</string>
|
||||
@@ -164,9 +164,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_expandable_card_title">Схаваць раскладвальную картку</string>
|
||||
<string name="revanced_hide_expandable_card_summary_on">Раскладвальная картка пад відэа схаваная</string>
|
||||
<string name="revanced_hide_expandable_card_summary_off">Раскладвальная картка пад відэа паказаная</string>
|
||||
<string name="revanced_hide_feed_survey_title">Схаваць апытанні стужкі</string>
|
||||
<string name="revanced_hide_feed_survey_summary_on">Апытанні каналаў схаваныя</string>
|
||||
<string name="revanced_hide_feed_survey_summary_off">Паказваюцца даследаванні кармоў</string>
|
||||
<string name="revanced_hide_floating_microphone_button_title">Схаваць плаваючую кнопку мікрафона</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_on">Плаваючая кнопка мікрафона ў пошуку схаваная</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_off">Плаваючая кнопка мікрафона ў пошуку паказана</string>
|
||||
@@ -192,7 +189,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_movies_section_summary_on">Раздзел фільмаў схаваны</string>
|
||||
<string name="revanced_hide_movies_section_summary_off">Паказваецца раздзел фільмаў</string>
|
||||
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
|
||||
This item appear in the subscription feed for future livestreams or unreleased videos. -->
|
||||
This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
|
||||
<string name="revanced_hide_notify_me_button_title">Схаваць кнопку \"Паведаміць мне\"</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_on">Кнопка «Паведаміць мне» схаваная</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_off">Кнопка «Паведаміць мне» паказаная</string>
|
||||
@@ -204,6 +201,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_show_more_button_title">Схаваць кнопку \"Паказаць больш\"</string>
|
||||
<string name="revanced_hide_show_more_button_summary_on">Кнопка «Паказаць больш» у выніках пошуку схаваная</string>
|
||||
<string name="revanced_hide_show_more_button_summary_off">Кнопка «Паказаць больш» у выніках пошуку паказаная</string>
|
||||
<string name="revanced_hide_surveys_title">Схаваць апытанні</string>
|
||||
<string name="revanced_hide_surveys_summary_on">Апытанні схаваныя</string>
|
||||
<string name="revanced_hide_surveys_summary_off">Апытанні паказаны</string>
|
||||
<string name="revanced_hide_ticket_shelf_title">Схаваць паліцу білетаў</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_on">Паліца білетаў схавана</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_off">Паліца білетаў паказана</string>
|
||||
@@ -251,8 +251,8 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_timed_reactions_summary_on">Часовыя рэакцыі схаваныя</string>
|
||||
<string name="revanced_hide_timed_reactions_summary_off">Паказваюцца рэакцыі па часе</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_title">Схаваць «Зводку відэа, згенэраваную штучным інтэлектам»</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">Раздзел зводкі відэа схаваны</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">Раздзел зводкі відэа паказаны</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">Раздзел згенераваных штучным інтэлектам відэа-рэзюмэ схаваны</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">Паказаны раздзел зводкі відэа, створанай штучным інтэлектам</string>
|
||||
<string name="revanced_hide_ask_section_title">Схаваць «Спытаць»</string>
|
||||
<string name="revanced_hide_ask_section_summary_on">Раздзел «Спытаць» схаваны</string>
|
||||
<string name="revanced_hide_ask_section_summary_off">Раздзел «Спытаць» паказаны</string>
|
||||
@@ -280,19 +280,19 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_description_components_screen_title">Апісанне відэа</string>
|
||||
<string name="revanced_hide_description_components_screen_summary">Схаваць або паказаць кампаненты апісання відэа</string>
|
||||
<string name="revanced_hide_filter_bar_screen_title">Панэль фільтраў</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">Схаваць ці паказаць панэль фільтраў у стужках, гісторыі, выніках пошуку і звязаных відэа</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">Схаваць або паказаць панэль фільтраў у стужках, звязаных відэа, выніках пошуку і гісторыі праглядаў</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_title">Схаваць у стужках</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_on">Схавана ў стужках</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_off">Паказана ў стужках</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">Схаваць у гісторыі</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">Схавана ў гісторыі</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">Паказана ў гісторыі</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">Схаваць у выніках пошуку</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">Схавана ў выніках пошуку</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">Паказана ў выніках пошуку</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">Схаваць у звязаных відэа</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">Схавана ў звязаных відэа</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">Паказана ў звязаных відэа</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">Схаваць у выніках пошуку</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">Схавана ў выніках пошуку</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">Паказана ў выніках пошуку</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">Схаваць у гісторыі праглядаў</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">Схавана ў гісторыі праглядаў</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">Паказаны ў гісторыі праглядаў</string>
|
||||
<string name="revanced_channel_screen_title">Старонка канала</string>
|
||||
<string name="revanced_channel_screen_summary">Схаваць або паказаць кампаненты старонкі канала</string>
|
||||
<!-- 'For You' should be translated using the same localized wording YouTube displays. -->
|
||||
@@ -316,11 +316,11 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_comments_screen_title">Каментарыі</string>
|
||||
<string name="revanced_comments_screen_summary">Схаваць або паказаць кампаненты раздзела каментарыяў</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_title">Схаваць зводку чата са штучным інтэлектам</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">Зводка чата схаваная</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">Зводка чата паказаная</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">Зводка чата са штучным інтэлектам схавана</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">Зводка чата са штучным інтэлектам паказана</string>
|
||||
<string name="revanced_hide_comments_ai_summary_title">Схаваць зводку каментарыяў са штучным інтэлектам</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_on">Зводка каментарыяў схаваная</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_off">Зводка каментарыяў паказаная</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_on">Зводка каментарыяў штучнага інтэлекту схавана</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_off">Зводка каментарыяў штучнага інтэлекту паказана</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_title">Схаваць правілы канала</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_on">Рэкамендацыі канала схаваны</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_off">Рэкамендацыі канала паказаны</string>
|
||||
@@ -419,7 +419,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_shopping_links_title">Схаваць спасылкі для пакупак</string>
|
||||
<string name="revanced_hide_shopping_links_summary_on">Спасылкі на пакупкі ў апісанні відэа схаваныя</string>
|
||||
<string name="revanced_hide_shopping_links_summary_off">Спасылкі на пакупкі ў апісанні відэа паказаны</string>
|
||||
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_view_products_banner_title">Схаваць банэр \"Прагледзець тавары\"</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_on">Банер «Паглядзець тавары» ў накладцы відэа схаваны</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_off">Банер «Паглядзець тавары» ў накладцы відэа паказаны</string>
|
||||
@@ -453,7 +452,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_summary_off">Будзе паказана дыялогавае акно</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">Гэта не абыходзіць узроставае абмежаванне. Ён проста прымае гэта аўтаматычна.</string>
|
||||
</patch>
|
||||
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch">
|
||||
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
|
||||
<string name="revanced_disable_chapter_skip_double_tap_title">Адключыць прапуск раздзела па двайным націску</string>
|
||||
<string name="revanced_disable_chapter_skip_double_tap_summary_on">Двайны націск ніколі не можа выклікаць прапуск да наступнага/папярэдняга раздзела</string>
|
||||
<string name="revanced_disable_chapter_skip_double_tap_summary_off">Двайны націск можа час ад часу выклікаць прапуск да наступнага/папярэдняга раздзела</string>
|
||||
@@ -469,8 +468,15 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_on">Кнопка \"Спампаваць\" адкрывае ваш знешні загрузнік</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_off">Кнопка \"Спампаваць\" адкрывае ўласную праграму загрузкі ў праграме</string>
|
||||
<string name="revanced_external_downloader_name_title">Назва пакета загрузніка</string>
|
||||
<string name="revanced_external_downloader_name_summary">Імя пакета ўсталяванай знешняй праграмы загрузкі, напрыклад NewPipe або Seal</string>
|
||||
<string name="revanced_external_downloader_name_summary">Назва пакета вашага ўсталяванага знешняга спампоўшчыка праграмы</string>
|
||||
<string name="revanced_external_downloader_other_item_hint">Увядзіце назву пакета</string>
|
||||
<string name="revanced_external_downloader_other_item">Іншае</string>
|
||||
<string name="revanced_external_downloader_not_found_title">Праграма не ўстаноўлена</string>
|
||||
<string name="revanced_external_downloader_not_installed_warning">%s не ўсталяваны. Калі ласка, усталюйце яго.</string>
|
||||
<string name="revanced_external_downloader_package_not_found_warning">"Не ўдалося знайсці ўстаноўленую праграму з назвай пакета: %s
|
||||
|
||||
Праверце, ці правільная назва пакета і ці ўстаноўлена праграма"</string>
|
||||
<string name="revanced_external_downloader_empty_warning">Назва пакета не можа быць пустой</string>
|
||||
</patch>
|
||||
<patch id="interaction.seekbar.disablePreciseSeekingGesturePatch">
|
||||
<string name="revanced_disable_precise_seeking_gesture_title">Адключыць жэст дакладнага пошуку</string>
|
||||
@@ -730,27 +736,28 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_disable_rolling_number_animations_summary_off">Пракатныя лічбы аніміраваныя</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.seekbar.hideSeekbarPatch">
|
||||
<string name="revanced_hide_seekbar_title">Схаваць панэль пошуку ў відэаплэеры</string>
|
||||
<string name="revanced_hide_seekbar_title">Схаваць панэль прагрэсу відэапрайгравальніка</string>
|
||||
<string name="revanced_hide_seekbar_summary_on">Панэль пошуку відэаплэера схавана</string>
|
||||
<string name="revanced_hide_seekbar_summary_off">Адлюстроўваецца панэль пошуку відэаплэера</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_title">Схаваць панэль пошуку ў мініяцюрах відэа</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_on">Панэль пошуку эскізаў схавана</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_off">Адлюстроўваецца панэль пошуку эскізаў</string>
|
||||
<!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
|
||||
<string name="revanced_hide_seekbar_thumbnail_title">Схаваць панэль прагрэсу з эскізамі відэа</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_on">Панэль прагрэсу з эскізамі відэа схавана</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_off">Панэль прагрэсу з эскізамі відэа паказана</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
|
||||
<string name="revanced_shorts_player_screen_title">Прайгравальнік Shorts</string>
|
||||
<string name="revanced_shorts_player_screen_summary">Схаваць або паказаць кампаненты ў прайгравальніку Shorts</string>
|
||||
<string name="revanced_shorts_player_screen_summary">Схаваць або паказаць кампаненты прайгравальніка Shorts</string>
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
|
||||
<string name="revanced_hide_shorts_home_title">Схаваць Shorts у стужцы «Галоўная»</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">Схавана ў стужцы «Галоўная» і звязаных відэа</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">Паказана ў стужцы «Галоўная» і звязаных відэа</string>
|
||||
<string name="revanced_hide_shorts_search_title">Схаваць Shorts у выніках пошуку</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">Схаваны ў выніках пошуку</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">Паказана ў выніках пошуку</string>
|
||||
<!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. -->
|
||||
<string name="revanced_hide_shorts_subscriptions_title">Схаваць Shorts у стужцы «Падпіскі»</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">Схавана ў стужцы «Падпіскі»</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">Паказана ў стужцы «Падпіскі»</string>
|
||||
<string name="revanced_hide_shorts_search_title">Схаваць Shorts у выніках пошуку</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">Схаваны ў выніках пошуку</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">Паказана ў выніках пошуку</string>
|
||||
<string name="revanced_hide_shorts_history_title">Схаваць Shorts з гісторыі праглядаў</string>
|
||||
<string name="revanced_hide_shorts_history_summary_on">Схавана ў гісторыі праглядаў</string>
|
||||
<string name="revanced_hide_shorts_history_summary_off">Паказаны ў гісторыі праглядаў</string>
|
||||
@@ -1191,8 +1198,6 @@ Second \"item\" text"</string>
|
||||
Гэта зменіць знешні выгляд і функцыі прыкладання, але могуць узнікнуць невядомыя пабочныя эфекты.
|
||||
|
||||
Калі пазней будзе адключана, рэкамендуецца ачысціць даныя прыкладання, каб пазбегнуць памылак у інтэрфейсе."</string>
|
||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_spoof_app_version_title'.
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch. -->
|
||||
<string name="revanced_spoof_app_version_target_title">Падробка мэтавай версіі праграмы</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_1">19.35.36 — Восстановить старые значки плеера Shorts</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_2">19.01.34 - Аднаўленне старых значкоў навігацыі</string>
|
||||
@@ -1461,10 +1466,18 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_playback_speed_dialog_button_summary_on">Кнопка паказана. Націсніце і ўтрымлівайце, каб скінуць хуткасць прайгравання да стандартнай</string>
|
||||
<string name="revanced_playback_speed_dialog_button_summary_off">Кнопка не паказваецца</string>
|
||||
</patch>
|
||||
<patch id="video.quality.button.videoQualityButtonPatch">
|
||||
<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_off">Кнопка не паказваецца</string>
|
||||
</patch>
|
||||
<patch id="video.speed.custom.customPlaybackSpeedPatch">
|
||||
<string name="revanced_custom_speed_menu_title">Меню пользовательской скорости воспроизведения</string>
|
||||
<string name="revanced_custom_speed_menu_summary_on">Меню пользовательской скорости отображается</string>
|
||||
<string name="revanced_custom_speed_menu_summary_off">Меню пользовательской скорости не отображается</string>
|
||||
<string name="revanced_restore_old_speed_menu_title">Аднавіць старое меню хуткасці прайгравання</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_on">Паказана старое меню хуткасці</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_off">Паказана сучаснае меню хуткасці</string>
|
||||
<string name="revanced_custom_playback_speeds_title">Карыстальніцкія хуткасці прайгравання</string>
|
||||
<string name="revanced_custom_playback_speeds_summary">Добавьте или измените пользовательскую скорость воспроизведения</string>
|
||||
<string name="revanced_custom_playback_speeds_invalid">Нестандартныя хуткасці павінны быць менш за %s</string>
|
||||
|
||||
@@ -137,7 +137,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_debug_logs_disabled">Отстраняването на грешки е деактивирано</string>
|
||||
<string name="revanced_debug_logs_none_found">Не са намерени логове</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Логовете са копирани</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Неуспешно експортиране на логове: $s</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Неуспешно експортиране на логове: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Изчистване на логовете за отстраняване на грешки</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Изчиства всички съхранени логове за отстраняване на грешки на ReVanced</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Логовете са изчистени</string>
|
||||
@@ -164,9 +164,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_expandable_card_title">Скриване на разгъваемата карта</string>
|
||||
<string name="revanced_hide_expandable_card_summary_on">Разгъваемата карта под видеоклиповете е скрита</string>
|
||||
<string name="revanced_hide_expandable_card_summary_off">Разгъваемата карта под видеоклиповете е показана</string>
|
||||
<string name="revanced_hide_feed_survey_title">Скриване на анкети в емисиите</string>
|
||||
<string name="revanced_hide_feed_survey_summary_on">Анкетите за емисии са скрити</string>
|
||||
<string name="revanced_hide_feed_survey_summary_off">Анкетите за емисии се показват</string>
|
||||
<string name="revanced_hide_floating_microphone_button_title">Плаващ бутон за микрофона</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_on">Плаващ бутон за микрофон при търсене е скрит</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_off">Плаващият бутон за микрофон в търсенето е показан</string>
|
||||
@@ -192,7 +189,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_movies_section_summary_on">Секцията с коментари е скрита</string>
|
||||
<string name="revanced_hide_movies_section_summary_off">Разделът за филми е показан</string>
|
||||
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
|
||||
This item appear in the subscription feed for future livestreams or unreleased videos. -->
|
||||
This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
|
||||
<string name="revanced_hide_notify_me_button_title">Скриване на бутона \"Уведоми ме\"</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_on">Бутонът за уведомяване е скрит</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_off">Бутонът за уведомяване е показан</string>
|
||||
@@ -204,6 +201,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_show_more_button_title">Скриване на бутона \"Покажи още\"</string>
|
||||
<string name="revanced_hide_show_more_button_summary_on">Бутонът за показване на още в резултатите от търсене е скрит</string>
|
||||
<string name="revanced_hide_show_more_button_summary_off">Бутонът за показване на още в резултатите от търсене е показан</string>
|
||||
<string name="revanced_hide_surveys_title">Скриване на проучвания</string>
|
||||
<string name="revanced_hide_surveys_summary_on">Анкетите са скрити</string>
|
||||
<string name="revanced_hide_surveys_summary_off">Анкетите са показани</string>
|
||||
<string name="revanced_hide_ticket_shelf_title">Скриване на рафта за билети</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_on">Рафтът за билети е скрит</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_off">Рафтът за билети е показан</string>
|
||||
@@ -251,8 +251,8 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_timed_reactions_summary_on">Времевите реакции са скрити</string>
|
||||
<string name="revanced_hide_timed_reactions_summary_off">Времевите реакции се показват</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_title">Скриване на \"AI-генерирано видео резюме\"</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">Скрит е разделът с видео резюме</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">Показва се разделът с видео резюме</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">Разделът за резюме на видеоклипове, генерирани от AI, е скрит</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">Разделът с генерирани от AI резюмета на видеоклипове е показан</string>
|
||||
<string name="revanced_hide_ask_section_title">Скриване на „Попитай“</string>
|
||||
<string name="revanced_hide_ask_section_summary_on">Скрит раздел „Попитай“</string>
|
||||
<string name="revanced_hide_ask_section_summary_off">Показване на раздел „Попитай“</string>
|
||||
@@ -280,19 +280,19 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_description_components_screen_title">Описание на видеото</string>
|
||||
<string name="revanced_hide_description_components_screen_summary">Скриване или показване на компонентите за описание на видеоклиповете</string>
|
||||
<string name="revanced_hide_filter_bar_screen_title">Лента с филтри</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">Скриване или показване на лентата с филтри в емисиите, историята, резултатите от търсенето и свързаните видеоклипове</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">Скриване или показване на лентата за филтри в емисиите, свързаните видеоклипове, резултатите от търсенето и историята на гледане</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_title">Скриване в емисии</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_on">Скрити в емисии</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_off">Показани в емисии</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">Скриване в историята</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">Скрити в историята</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">Показани в историята</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">Скриване в резултатите от търсенето</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">Скрито в резултатите от търсенето</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">Показано в резултатите от търсенето</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">Скриване в сродни видеоклипове</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">Скриване в сродни видеоклипове</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">Показано в сродни видеоклипове</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">Скриване в резултатите от търсенето</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">Скрито в резултатите от търсенето</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">Показано в резултатите от търсенето</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">Скриване в историята на гледанията</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">Скрито в историята на гледане</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">Показано в историята на гледанията</string>
|
||||
<string name="revanced_channel_screen_title">Страница на канала</string>
|
||||
<string name="revanced_channel_screen_summary">Скриване или показване на компоненти на страницата на канала</string>
|
||||
<!-- 'For You' should be translated using the same localized wording YouTube displays. -->
|
||||
@@ -315,12 +315,12 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_visit_store_button_summary_off">Бутонът „Посетете магазина“ е показан</string>
|
||||
<string name="revanced_comments_screen_title">Коментари</string>
|
||||
<string name="revanced_comments_screen_summary">Скриване или показване на секцията за коментари</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_title">Скриване на резюмето на AI Chat</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">Резюмето на чата е скрито</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">Резюмето на чата е показано</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_title">Скриване на резюмето на AI чата</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">Резюмето на AI чата е скрито</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">Резюмето на AI чата е показано</string>
|
||||
<string name="revanced_hide_comments_ai_summary_title">Скриване на резюмето на AI коментарите</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_on">Резюмето на коментарите е скрито</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_off">Резюмето на коментарите е показано</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_on">Резюмето на AI коментари е скрито</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_off">Резюмето на AI коментари е показано</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_title">Скриване на насоките на канала</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_on">Указанията за канала са скрити</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_off">Указанията за канала са показани</string>
|
||||
@@ -419,7 +419,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_shopping_links_title">Скриване на връзки за пазаруване</string>
|
||||
<string name="revanced_hide_shopping_links_summary_on">Линковете за пазаруване във видео описанието са скрити</string>
|
||||
<string name="revanced_hide_shopping_links_summary_off">Линковете за пазаруване в описанието на видеоклипа са показани</string>
|
||||
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_view_products_banner_title">Скриване на банера „Преглед на продукти“</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_on">Банерът за преглед на продукти във видео наслагването е скрит</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_off">Банерът за преглед на продукти във видео наслагването е показан</string>
|
||||
@@ -453,7 +452,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_summary_off">Диалоговият прозорец ще бъде показан</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">Тази функция не заобикаля възрастовото ограничение. Тя просто приема възрастовата граница автоматично.</string>
|
||||
</patch>
|
||||
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch">
|
||||
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
|
||||
<string name="revanced_disable_chapter_skip_double_tap_title">Деактивиране на пропускане на глава с двойно докосване</string>
|
||||
<string name="revanced_disable_chapter_skip_double_tap_summary_on">Двойното докосване никога не може да предизвика пропускане до следваща/предишна глава</string>
|
||||
<string name="revanced_disable_chapter_skip_double_tap_summary_off">Двойното докосване може понякога да предизвика пропускане до следваща/предишна глава</string>
|
||||
@@ -469,8 +468,15 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_on">Бутонът за изтегляне отваря избраното от Вас външно приложение за изтегляне</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_off">Бутонът за изтегляне отваря вграденото приложение за изтегляне</string>
|
||||
<string name="revanced_external_downloader_name_title">Име на пакета на изтеглящото приложение</string>
|
||||
<string name="revanced_external_downloader_name_summary">Име на пакета на приложението за изтегляне, като NewPipe или Seal</string>
|
||||
<string name="revanced_external_downloader_name_summary">Име на пакета на вашето инсталирано външно приложение за изтегляне</string>
|
||||
<string name="revanced_external_downloader_other_item_hint">Въведете името на пакета</string>
|
||||
<string name="revanced_external_downloader_other_item">Други</string>
|
||||
<string name="revanced_external_downloader_not_found_title">Приложението не е инсталирано</string>
|
||||
<string name="revanced_external_downloader_not_installed_warning">%s не е инсталиран. Инсталирайте го.</string>
|
||||
<string name="revanced_external_downloader_package_not_found_warning">"Не може да бъде намерено инсталирано приложение с име на пакет: %s
|
||||
|
||||
Проверете дали името на пакета е правилно и приложението е инсталирано"</string>
|
||||
<string name="revanced_external_downloader_empty_warning">Името на пакета не може да бъде празно</string>
|
||||
</patch>
|
||||
<patch id="interaction.seekbar.disablePreciseSeekingGesturePatch">
|
||||
<string name="revanced_disable_precise_seeking_gesture_title">Деактивиране на жеста за точно търсене</string>
|
||||
@@ -730,27 +736,28 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_disable_rolling_number_animations_summary_off">Анимацията е активирана</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.seekbar.hideSeekbarPatch">
|
||||
<string name="revanced_hide_seekbar_title">Скриване на лента за време на плейъра</string>
|
||||
<string name="revanced_hide_seekbar_title">Скриване на лентата за търсене на видео плейър</string>
|
||||
<string name="revanced_hide_seekbar_summary_on">Лентата за време на плейъра е скрита</string>
|
||||
<string name="revanced_hide_seekbar_summary_off">Лентата за време на плейъра се показва</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_title">Скр. лента за време при миниатюрите</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_on">Лентата за време при миниатюрите е скрита</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_off">Лентата за време при миниатюрите се показва</string>
|
||||
<!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
|
||||
<string name="revanced_hide_seekbar_thumbnail_title">Скриване на лентата за търсене на миниатюри на видеоклипове</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_on">Лентата за търсене на миниатюри на видеоклипове е скрита</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_off">Лентата за търсене на миниатюри на видеоклипове е показана</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
|
||||
<string name="revanced_shorts_player_screen_title">Играч на Shorts</string>
|
||||
<string name="revanced_shorts_player_screen_summary">Скриване или показване на компоненти в Shorts плейъра</string>
|
||||
<string name="revanced_shorts_player_screen_summary">Скриване или показване на компонентите на плейъра за Shorts</string>
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
|
||||
<string name="revanced_hide_shorts_home_title">Скриване на Shorts в емисията Начало</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">Скрито в емисията Начало и свързани видеоклипове</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">Показано в емисията Начало и свързани видеоклипове</string>
|
||||
<string name="revanced_hide_shorts_search_title">Shorts в резултатите от търсенето</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">Скрити в резултатите от търсенето</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">Показано в резултатите от търсенето</string>
|
||||
<!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. -->
|
||||
<string name="revanced_hide_shorts_subscriptions_title">Скриване на Shorts в емисията Абонаменти</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">Скрито в емисията Абонаменти</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">Показано в емисията Абонаменти</string>
|
||||
<string name="revanced_hide_shorts_search_title">Shorts в резултатите от търсенето</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">Скрити в резултатите от търсенето</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">Показано в резултатите от търсенето</string>
|
||||
<string name="revanced_hide_shorts_history_title">Скриване на шортите в историята на гледане</string>
|
||||
<string name="revanced_hide_shorts_history_summary_on">Скрито в историята на гледане</string>
|
||||
<string name="revanced_hide_shorts_history_summary_off">Показва се в историята на гледане</string>
|
||||
@@ -1190,8 +1197,6 @@ Second \"item\" text"</string>
|
||||
Това ще промени външния вид и функциите на приложението, но може да възникнат неизвестни странични ефекти.
|
||||
|
||||
Ако по-късно бъде изключено, препоръчително е да изчистите данните на приложението, за да предотвратите грешки в потребителския интерфейс."</string>
|
||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_spoof_app_version_title'.
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch. -->
|
||||
<string name="revanced_spoof_app_version_target_title">Подлъгване за версията на</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_1">19.35.36 - Възстановете старите икони на Shorts в плейъра</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_2">19.01.34 - Възстановяване на стари икони за навигация</string>
|
||||
@@ -1460,10 +1465,18 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_playback_speed_dialog_button_summary_on">Бутонът е показан. Докоснете и задръжте, за да върнете скоростта на възпроизвеждане към стойността по подразбиране</string>
|
||||
<string name="revanced_playback_speed_dialog_button_summary_off">Бутонът не е показан</string>
|
||||
</patch>
|
||||
<patch id="video.quality.button.videoQualityButtonPatch">
|
||||
<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_off">Бутонът не е показан</string>
|
||||
</patch>
|
||||
<patch id="video.speed.custom.customPlaybackSpeedPatch">
|
||||
<string name="revanced_custom_speed_menu_title">Менюто за потребителска скорост</string>
|
||||
<string name="revanced_custom_speed_menu_summary_on">Менюто за потребителска скорост се показва</string>
|
||||
<string name="revanced_custom_speed_menu_summary_off">Менюто за потребителска скорост не се показва</string>
|
||||
<string name="revanced_restore_old_speed_menu_title">Възстановяване на старото меню за скорост на възпроизвеждане</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_on">Показва се старото меню за скорост</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_off">Показва се модерното меню за скорост</string>
|
||||
<string name="revanced_custom_playback_speeds_title">Персонализирани скорости на възпроизвеждане</string>
|
||||
<string name="revanced_custom_playback_speeds_summary">Добавете или променете скоростa на възпроизвеждане</string>
|
||||
<string name="revanced_custom_playback_speeds_invalid">Персонализираните скорости трябва да са по-малки от %s</string>
|
||||
|
||||
@@ -133,7 +133,7 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
|
||||
<string name="revanced_debug_logs_disabled">ডিবাগ লগিং নিষ্ক্রিয় করা হয়েছে</string>
|
||||
<string name="revanced_debug_logs_none_found">কোনো লগ পাওয়া যায়নি</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">লগ অনুলিপি করা হয়েছে</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">লগ রপ্তানি করতে ব্যর্থ: $s</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">লগ এক্সপোর্ট করা যায়নি: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">ডিবাগ লগগুলি সাফ করুন</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">সমস্ত সঞ্চিত ReVanced ডিবাগ লগ সাফ করে</string>
|
||||
<string name="revanced_debug_logs_clear_toast">লগ সাফ করা হয়েছে</string>
|
||||
@@ -160,9 +160,6 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
|
||||
<string name="revanced_hide_expandable_card_title">প্রসারিত কার্ড লুকান</string>
|
||||
<string name="revanced_hide_expandable_card_summary_on">ভিডিওর নিচে প্রসারিত কার্ড লুকানো আছে</string>
|
||||
<string name="revanced_hide_expandable_card_summary_off">ভিডিওর নিচে প্রসারিত কার্ড দেখানো আছে</string>
|
||||
<string name="revanced_hide_feed_survey_title">ফিড জরিপ লুকান</string>
|
||||
<string name="revanced_hide_feed_survey_summary_on">ফিড জরিপ লুকিয়ে রয়েছে</string>
|
||||
<string name="revanced_hide_feed_survey_summary_off">ফিড জরিপ প্রদর্শিত হয়েছে</string>
|
||||
<string name="revanced_hide_floating_microphone_button_title">ভাসমান মাইক্রোফোন বোতাম লুকান</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_on">অনুসন্ধানে ফ্লোটিং মাইক্রোফোন বোতাম লুকানো আছে</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_off">অনুসন্ধানে ভাসমান মাইক্রোফোন বোতাম দেখানো হয়</string>
|
||||
@@ -188,7 +185,7 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
|
||||
<string name="revanced_hide_movies_section_summary_on">চলচ্চিত্র বিভাগ লুকিয়ে রয়েছে</string>
|
||||
<string name="revanced_hide_movies_section_summary_off">চলচ্চিত্র বিভাগ প্রদর্শিত হয়েছে</string>
|
||||
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
|
||||
This item appear in the subscription feed for future livestreams or unreleased videos. -->
|
||||
This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
|
||||
<string name="revanced_hide_notify_me_button_title">\'আমাকে জানান\' বোতাম লুকান</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_on">আমাকে জানান বোতামটি লুকানো আছে</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_off">আমাকে জানান বোতামটি দেখানো হয়েছে</string>
|
||||
@@ -200,6 +197,9 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
|
||||
<string name="revanced_hide_show_more_button_title">\'আরও দেখান\' বোতাম লুকান</string>
|
||||
<string name="revanced_hide_show_more_button_summary_on">অনুসন্ধান ফলাফলে \"আরও দেখান\" বোতামটি লুকানো আছে</string>
|
||||
<string name="revanced_hide_show_more_button_summary_off">অনুসন্ধান ফলাফলে \"আরও দেখান\" বোতামটি দেখানো হয়েছে</string>
|
||||
<string name="revanced_hide_surveys_title">সার্ভে লুকান</string>
|
||||
<string name="revanced_hide_surveys_summary_on">জরিপগুলি লুকানো হয়েছে</string>
|
||||
<string name="revanced_hide_surveys_summary_off">জরিপগুলি দেখানো হয়েছে</string>
|
||||
<string name="revanced_hide_ticket_shelf_title">টিকিট তাক লুকান</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_on">টিকিট তাক লুকানো আছে</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_off">টিকিট তাক দেখানো হয়েছে</string>
|
||||
@@ -247,8 +247,8 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
|
||||
<string name="revanced_hide_timed_reactions_summary_on">সময় অনুযায়ী প্রতিক্রিয়া লুকিয়ে রয়েছে</string>
|
||||
<string name="revanced_hide_timed_reactions_summary_off">সময় অনুযায়ী প্রতিক্রিয়া প্রদর্শিত হয়েছে</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_title">\'AI-জেনারেটেড ভিডিও সারসংক্ষেপ\' লুকান</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">ভিডিও সারসংক্ষেপ বিভাগ লুকানো আছে</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">ভিডিও সারসংক্ষেপ বিভাগ দেখানো হয়েছে</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">এআই-জেনারেটেড ভিডিও সারাংশ বিভাগ লুকানো আছে</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">এআই-জেনারেটেড ভিডিও সারাংশ বিভাগ দেখানো হয়েছে</string>
|
||||
<string name="revanced_hide_ask_section_title">জিজ্ঞাসা লুকান</string>
|
||||
<string name="revanced_hide_ask_section_summary_on">জিজ্ঞাসা বিভাগ লুকানো আছে</string>
|
||||
<string name="revanced_hide_ask_section_summary_off">জিজ্ঞাসা বিভাগ দেখানো হয়েছে</string>
|
||||
@@ -276,19 +276,19 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
|
||||
<string name="revanced_hide_description_components_screen_title">ভিডিওর বিবরণ</string>
|
||||
<string name="revanced_hide_description_components_screen_summary">ভিডিও বিবরণ এর উপাদান লুকান বা প্রদর্শন করুন</string>
|
||||
<string name="revanced_hide_filter_bar_screen_title">ফিল্টার বার</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">ফিড, ইতিহাস, অনুসন্ধান ফলাফল এবং সম্পর্কিত ভিডিওগুলিতে ফিল্টার বার লুকান বা দেখান</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">ফিড, সম্পর্কিত ভিডিও, অনুসন্ধান ফলাফল এবং দেখার ইতিহাসে ফিল্টার বার লুকান বা দেখান</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_title">ফিডে লুকান</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_on">ফিডে লুকানো</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_off">ফিডে দেখানো হয়েছে</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">ইতিহাসে লুকান</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">ইতিহাসে লুকানো</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">ইতিহাসে দেখানো হয়েছে</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">অনুসন্ধান ফলাফলে লুকান</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">অনুসন্ধান ফলাফলে লুকানো আছে</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">অনুসন্ধান ফলাফলে দেখানো হয়েছে</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">সম্পর্কিত ভিডিওতে লুকান</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">সম্পর্কিত ভিডিওতে লুকিয়ে রয়েছে</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">সম্পর্কিত ভিডিওতে প্রদর্শিত হয়েছে</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">অনুসন্ধান ফলাফলে লুকান</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">অনুসন্ধান ফলাফলে লুকানো আছে</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">অনুসন্ধান ফলাফলে দেখানো হয়েছে</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">দেখার ইতিহাসে লুকান</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">দেখার ইতিহাসে লুকানো</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">দেখার ইতিহাসে দেখানো হয়েছে</string>
|
||||
<string name="revanced_channel_screen_title">চ্যানেল পৃষ্ঠা</string>
|
||||
<string name="revanced_channel_screen_summary">চ্যানেল পৃষ্ঠার উপাদানগুলি লুকান বা দেখান</string>
|
||||
<!-- 'For You' should be translated using the same localized wording YouTube displays. -->
|
||||
@@ -311,12 +311,12 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
|
||||
<string name="revanced_hide_visit_store_button_summary_off">স্টোর ভিজিট বাটন দেখানো আছে</string>
|
||||
<string name="revanced_comments_screen_title">মন্তব্য</string>
|
||||
<string name="revanced_comments_screen_summary">মন্তব্য বিভাগের উপাদানগুলি লুকান বা দেখান৷</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_title">এআই চ্যাট সংক্ষিপ্তসার লুকান</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">চ্যাট সংক্ষিপ্তসার লুকানো আছে</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">চ্যাট সংক্ষিপ্তসার দেখানো হয়েছে</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_title">এআই চ্যাট সারাংশ লুকান</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">এআই চ্যাট সারাংশ লুকানো আছে</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">এআই চ্যাট সারাংশ দেখানো হয়েছে</string>
|
||||
<string name="revanced_hide_comments_ai_summary_title">এআই মন্তব্য সংক্ষিপ্তসার লুকান</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_on">মন্তব্য সংক্ষিপ্তসার লুকানো আছে</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_off">মন্তব্য সংক্ষিপ্তসার দেখানো হয়েছে</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_on">এআই মন্তব্য সারাংশ লুকানো আছে</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_off">এআই মন্তব্য সারাংশ দেখানো হয়েছে</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_title">চ্যানেল নির্দেশিকা লুকান</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_on">চ্যানেল নির্দেশিকা লুকানো হয়েছে</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_off">চ্যানেল নির্দেশিকা দেখানো হয়েছে</string>
|
||||
@@ -415,7 +415,6 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
|
||||
<string name="revanced_hide_shopping_links_title">কেনাকাটার লিঙ্ক লুকান</string>
|
||||
<string name="revanced_hide_shopping_links_summary_on">ভিডিও বিবরণে কেনাকাটার লিঙ্ক লুকানো আছে</string>
|
||||
<string name="revanced_hide_shopping_links_summary_off">ভিডিও বর্ণনায় কেনাকাটার লিঙ্ক দেখানো হয়</string>
|
||||
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_view_products_banner_title">\'পণ্য দেখুন\' ব্যানার লুকান</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_on">ভিডিও ওভারলেতে \"পণ্য দেখুন\" ব্যানার লুকানো আছে</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_off">ভিডিও ওভারলেতে \"পণ্য দেখুন\" ব্যানার দেখানো হয়েছে</string>
|
||||
@@ -449,7 +448,7 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
|
||||
<string name="revanced_remove_viewer_discretion_dialog_summary_off">ডায়ালগ প্রদর্শিত হবে</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">এটি বয়সের সীমাবদ্ধতাকে বাইপাস করে না। এটা শুধু স্বয়ংক্রিয়ভাবে গ্রহণ করে।</string>
|
||||
</patch>
|
||||
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch">
|
||||
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
|
||||
<string name="revanced_disable_chapter_skip_double_tap_title">ডাবল ট্যাপ অধ্যায় স্কিপ অক্ষম করুন</string>
|
||||
<string name="revanced_disable_chapter_skip_double_tap_summary_on">ডাবল ট্যাপ কখনও পরবর্তী/পূর্ববর্তী অধ্যায়ে স্কিপ ট্রিগার করতে পারে না</string>
|
||||
<string name="revanced_disable_chapter_skip_double_tap_summary_off">ডাবল ট্যাপ মাঝে মাঝে পরবর্তী/পূর্ববর্তী অধ্যায়ে স্কিপ ট্রিগার করতে পারে</string>
|
||||
@@ -465,8 +464,15 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
|
||||
<string name="revanced_external_downloader_action_button_summary_on">ডাউনলোড বোতামটি আপনার বাহিরের ডাউনলোডার খুলবে</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_off">ডাউনলোড বোতামটি নেটিভ ইন-অ্যাপ ডাউনলোডার খুলবে</string>
|
||||
<string name="revanced_external_downloader_name_title">ডাউনলোডারের প্যাকেজ নাম</string>
|
||||
<string name="revanced_external_downloader_name_summary">আপনার ইনস্টল করা বাইরের ডাউনলোডার অ্যাপের প্যাকেজ নাম, যেমন NewPipe বা Seal</string>
|
||||
<string name="revanced_external_downloader_name_summary">আপনার ইনস্টল করা বাহ্যিক ডাউনলোডার অ্যাপের প্যাকেজের নাম</string>
|
||||
<string name="revanced_external_downloader_other_item_hint">প্যাকেজের নাম লিখুন</string>
|
||||
<string name="revanced_external_downloader_other_item">অন্যান্য</string>
|
||||
<string name="revanced_external_downloader_not_found_title">অ্যাপ ইনস্টল করা নেই</string>
|
||||
<string name="revanced_external_downloader_not_installed_warning">%s ইনস্টল করা নেই, ইনস্টল করুন।</string>
|
||||
<string name="revanced_external_downloader_package_not_found_warning">"প্যাকেজের নাম: %s সহ ইনস্টল করা অ্যাপটি খুঁজে পাওয়া যায়নি
|
||||
|
||||
প্যাকেজের নামটি সঠিক এবং অ্যাপটি ইনস্টল করা আছে কিনা তা যাচাই করুন"</string>
|
||||
<string name="revanced_external_downloader_empty_warning">প্যাকেজের নাম খালি রাখা যাবে না</string>
|
||||
</patch>
|
||||
<patch id="interaction.seekbar.disablePreciseSeekingGesturePatch">
|
||||
<string name="revanced_disable_precise_seeking_gesture_title">ভিডিওর নির্দিষ্ট অংশে যাওয়ার অঙ্গভঙ্গি নিষ্ক্রিয় করুন</string>
|
||||
@@ -726,27 +732,28 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
|
||||
<string name="revanced_disable_rolling_number_animations_summary_off">রোলিং নাম্বার অ্যানিমেটেড</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.seekbar.hideSeekbarPatch">
|
||||
<string name="revanced_hide_seekbar_title">ভিডিও প্লেয়ারে সিকবার লুকান</string>
|
||||
<string name="revanced_hide_seekbar_title">ভিডিও প্লেয়ারের সিকবার লুকান</string>
|
||||
<string name="revanced_hide_seekbar_summary_on">ভিডিও প্লেয়ারে সিকবার লুকিয়ে রয়েছে</string>
|
||||
<string name="revanced_hide_seekbar_summary_off">ভিডিও প্লেয়ারে সিকবার প্রদর্শিত হয়েছে</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_title">ভিডিও থাম্বনেইলে সিকবার লুকান</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_on">থাম্বনেইলে সিকবার লুকিয়ে রয়েছে</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_off">থাম্বনেইলে সিকবার প্রদর্শিত হয়েছে</string>
|
||||
<!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
|
||||
<string name="revanced_hide_seekbar_thumbnail_title">ভিডিও থাম্বনেইল সিকবার লুকান</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_on">ভিডিও থাম্বনেইল সিকবার লুকানো আছে</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_off">ভিডিও থাম্বনেইল সিকবার দেখানো হয়েছে</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
|
||||
<string name="revanced_shorts_player_screen_title">Shorts প্লেয়ার</string>
|
||||
<string name="revanced_shorts_player_screen_summary">Shorts প্লেয়ারে উপাদান লুকানো বা দেখানো</string>
|
||||
<string name="revanced_shorts_player_screen_summary">Shorts প্লেয়ারের উপাদান লুকান বা দেখান</string>
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
|
||||
<string name="revanced_hide_shorts_home_title">হোম ফিডে Shorts লুকান</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">হোম ফিড এবং সম্পর্কিত ভিডিওতে লুকানো আছে</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">হোম ফিড এবং সম্পর্কিত ভিডিওতে দেখানো হয়েছে</string>
|
||||
<string name="revanced_hide_shorts_search_title">অনুসন্ধান ফলাফলে Shorts লুকান</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">অনুসন্ধান ফলাফলে লুকানো</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">সার্চ রেজাল্টে দেখানো হয়েছে</string>
|
||||
<!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. -->
|
||||
<string name="revanced_hide_shorts_subscriptions_title">সাবস্ক্রিপশনস ফিডে Shorts লুকান</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">সাবস্ক্রিপশনস ফিডে লুকানো আছে</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">সাবস্ক্রিপশনস ফিডে দেখানো হয়েছে</string>
|
||||
<string name="revanced_hide_shorts_search_title">অনুসন্ধান ফলাফলে Shorts লুকান</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">অনুসন্ধান ফলাফলে লুকানো</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">সার্চ রেজাল্টে দেখানো হয়েছে</string>
|
||||
<string name="revanced_hide_shorts_history_title">Shortsগুলিকে ওয়াচ ইতিহাসে লুকান</string>
|
||||
<string name="revanced_hide_shorts_history_summary_on">ওয়াচ হিস্ট্রিতে লুকানো</string>
|
||||
<string name="revanced_hide_shorts_history_summary_off">ওয়াচ ইতিহাসে দেখানো</string>
|
||||
@@ -1186,8 +1193,6 @@ YouTube সেটিংসে অটো প্লে পরিবর্তন
|
||||
এটি অ্যাপ্লিকেশনটির চেহারা এবং বৈশিষ্ট্য পরিবর্তন করবে, তবে অজানা পার্শ্ব প্রতিক্রিয়া হতে পারে।
|
||||
|
||||
পরে যদি বন্ধ করা হয়, UI বাগ এড়াতে অ্যাপ্লিকেশন ডেটা পরিষ্কার করার পরামর্শ দেওয়া হয়।"</string>
|
||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_spoof_app_version_title'.
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch. -->
|
||||
<string name="revanced_spoof_app_version_target_title">স্পুফ অ্যাপ সংস্করণ লক্ষ্য</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_1">19.35.36 - পুরনো Shorts প্লেয়ার আইকন পুনরুদ্ধার করুন</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_2">19.01.34 - পুরনো নেভিগেশন আইকন পুনরুদ্ধার করুন</string>
|
||||
@@ -1456,10 +1461,18 @@ DeArrow সম্পর্কে আরও জানতে এখানে ট
|
||||
<string name="revanced_playback_speed_dialog_button_summary_on">বোতামটি দেখানো হয়েছে। প্লেব্যাক স্পীড ডিফল্টে রিসেট করতে ট্যাপ করে ধরে রাখুন।</string>
|
||||
<string name="revanced_playback_speed_dialog_button_summary_off">বোতাম প্রদর্শিত হয়নি</string>
|
||||
</patch>
|
||||
<patch id="video.quality.button.videoQualityButtonPatch">
|
||||
<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_off">বোতামটি দেখানো হয়নি।</string>
|
||||
</patch>
|
||||
<patch id="video.speed.custom.customPlaybackSpeedPatch">
|
||||
<string name="revanced_custom_speed_menu_title">কাস্টম প্লেব্যাক গতি মেনু</string>
|
||||
<string name="revanced_custom_speed_menu_summary_on">কাস্টম স্পিড মেনু দেখানো হচ্ছে</string>
|
||||
<string name="revanced_custom_speed_menu_summary_off">কাস্টম স্পিড মেনু দেখানো হচ্ছে না</string>
|
||||
<string name="revanced_restore_old_speed_menu_title">পুরানো প্লেব্যাক গতি মেনু পুনরুদ্ধার করুন</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_on">পুরানো গতির মেনু দেখানো হয়েছে</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_off">আধুনিক গতির মেনু দেখানো হয়েছে</string>
|
||||
<string name="revanced_custom_playback_speeds_title">নিজস্ব প্লেব্যাক স্পিড</string>
|
||||
<string name="revanced_custom_playback_speeds_summary">কাস্টম প্লেব্যাক গতি যোগ করুন অথবা পরিবর্তন করুন</string>
|
||||
<string name="revanced_custom_playback_speeds_invalid">কাস্টম গতি %s এর চেয়ে কম হতে হবে</string>
|
||||
|
||||
@@ -40,7 +40,7 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.general.hideLayoutComponentsPatch">
|
||||
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
|
||||
This item appear in the subscription feed for future livestreams or unreleased videos. -->
|
||||
This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
|
||||
<!-- 'Show more' should be translated with the same localized wording that YouTube displays.
|
||||
This button usually appears when searching for a YT creator. -->
|
||||
<!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. -->
|
||||
@@ -58,7 +58,6 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="ad.general.hideAdsResourcePatch">
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
|
||||
</patch>
|
||||
<patch id="ad.getpremium.hideGetPremiumPatch">
|
||||
</patch>
|
||||
@@ -68,7 +67,7 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="interaction.dialog.removeViewerDiscretionDialogPatch">
|
||||
</patch>
|
||||
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch">
|
||||
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
|
||||
</patch>
|
||||
<patch id="interaction.downloads.downloadsResourcePatch">
|
||||
<!-- 'Download action button' should be translated using the same wording as the translation of 'revanced_hide_download_button_title'. -->
|
||||
@@ -128,6 +127,7 @@ Second \"item\" text"</string>
|
||||
<patch id="layout.hide.rollingnumber.disableRollingNumberAnimationPatch">
|
||||
</patch>
|
||||
<patch id="layout.hide.seekbar.hideSeekbarPatch">
|
||||
<!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
|
||||
</patch>
|
||||
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
|
||||
@@ -170,8 +170,6 @@ Second \"item\" text"</string>
|
||||
<patch id="layout.formfactor.changeFormFactorPatch">
|
||||
</patch>
|
||||
<patch id="layout.spoofappversion.spoofAppVersionPatch">
|
||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_spoof_app_version_title'.
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch. -->
|
||||
</patch>
|
||||
<patch id="layout.startpage.changeStartPagePatch">
|
||||
</patch>
|
||||
@@ -224,6 +222,8 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="video.speed.button.playbackSpeedButtonPatch">
|
||||
</patch>
|
||||
<patch id="video.quality.button.videoQualityButtonPatch">
|
||||
</patch>
|
||||
<patch id="video.speed.custom.customPlaybackSpeedPatch">
|
||||
</patch>
|
||||
<patch id="video.speed.remember.rememberPlaybackSpeedPatch">
|
||||
|
||||
@@ -40,7 +40,7 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.general.hideLayoutComponentsPatch">
|
||||
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
|
||||
This item appear in the subscription feed for future livestreams or unreleased videos. -->
|
||||
This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
|
||||
<!-- 'Show more' should be translated with the same localized wording that YouTube displays.
|
||||
This button usually appears when searching for a YT creator. -->
|
||||
<!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. -->
|
||||
@@ -58,7 +58,6 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="ad.general.hideAdsResourcePatch">
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
|
||||
</patch>
|
||||
<patch id="ad.getpremium.hideGetPremiumPatch">
|
||||
</patch>
|
||||
@@ -68,7 +67,7 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="interaction.dialog.removeViewerDiscretionDialogPatch">
|
||||
</patch>
|
||||
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch">
|
||||
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
|
||||
</patch>
|
||||
<patch id="interaction.downloads.downloadsResourcePatch">
|
||||
<!-- 'Download action button' should be translated using the same wording as the translation of 'revanced_hide_download_button_title'. -->
|
||||
@@ -128,6 +127,7 @@ Second \"item\" text"</string>
|
||||
<patch id="layout.hide.rollingnumber.disableRollingNumberAnimationPatch">
|
||||
</patch>
|
||||
<patch id="layout.hide.seekbar.hideSeekbarPatch">
|
||||
<!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
|
||||
</patch>
|
||||
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
|
||||
@@ -170,8 +170,6 @@ Second \"item\" text"</string>
|
||||
<patch id="layout.formfactor.changeFormFactorPatch">
|
||||
</patch>
|
||||
<patch id="layout.spoofappversion.spoofAppVersionPatch">
|
||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_spoof_app_version_title'.
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch. -->
|
||||
</patch>
|
||||
<patch id="layout.startpage.changeStartPagePatch">
|
||||
</patch>
|
||||
@@ -224,6 +222,8 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="video.speed.button.playbackSpeedButtonPatch">
|
||||
</patch>
|
||||
<patch id="video.quality.button.videoQualityButtonPatch">
|
||||
</patch>
|
||||
<patch id="video.speed.custom.customPlaybackSpeedPatch">
|
||||
</patch>
|
||||
<patch id="video.speed.remember.rememberPlaybackSpeedPatch">
|
||||
|
||||
@@ -137,7 +137,7 @@ Nebudete informováni o žádné neočekávané události."</string>
|
||||
<string name="revanced_debug_logs_disabled">Ladění je vypnuto</string>
|
||||
<string name="revanced_debug_logs_none_found">Nebyly nalezeny žádné protokoly</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Protokoly zkopírovány</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Nepodařilo se exportovat protokoly: $s</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Nepodařilo se exportovat protokoly: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Vymazat ladicí protokoly</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Vymaže všechny uložené ladicí protokoly ReVanced</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Protokoly vymazány</string>
|
||||
@@ -164,9 +164,6 @@ Nebudete informováni o žádné neočekávané události."</string>
|
||||
<string name="revanced_hide_expandable_card_title">Skrýt rozbalitelnou kartu</string>
|
||||
<string name="revanced_hide_expandable_card_summary_on">Rozbalitelná karta pod videi je skryta</string>
|
||||
<string name="revanced_hide_expandable_card_summary_off">Rozbalitelná karta pod videi je zobrazena</string>
|
||||
<string name="revanced_hide_feed_survey_title">Skrýt průzkumy feedu</string>
|
||||
<string name="revanced_hide_feed_survey_summary_on">Průzkumy feedu jsou skryty</string>
|
||||
<string name="revanced_hide_feed_survey_summary_off">Průzkumy feedu jsou zobrazeny</string>
|
||||
<string name="revanced_hide_floating_microphone_button_title">Skrýt plovoucí tlačítko mikrofonu</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_on">Plovoucí tlačítko mikrofonu ve vyhledávání je skryto</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_off">Plovoucí tlačítko mikrofonu ve vyhledávání je zobrazeno</string>
|
||||
@@ -192,7 +189,7 @@ Nebudete informováni o žádné neočekávané události."</string>
|
||||
<string name="revanced_hide_movies_section_summary_on">Sekce Filmy je skrytá</string>
|
||||
<string name="revanced_hide_movies_section_summary_off">Sekce Filmy je viditelná</string>
|
||||
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
|
||||
This item appear in the subscription feed for future livestreams or unreleased videos. -->
|
||||
This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
|
||||
<string name="revanced_hide_notify_me_button_title">Skrýt tlačitko \'Upozorněte mě\'</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_on">Tlačítko \"Upozornit mě\" je skryto</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_off">Tlačítko \"Upozornit mě\" je zobrazeno</string>
|
||||
@@ -204,6 +201,9 @@ Nebudete informováni o žádné neočekávané události."</string>
|
||||
<string name="revanced_hide_show_more_button_title">Skrýt tlačítko „Zobrazit více“</string>
|
||||
<string name="revanced_hide_show_more_button_summary_on">Tlačítko \"Zobrazit více\" ve výsledcích vyhledávání je skryto</string>
|
||||
<string name="revanced_hide_show_more_button_summary_off">Tlačítko \"Zobrazit více\" ve výsledcích vyhledávání je zobrazeno</string>
|
||||
<string name="revanced_hide_surveys_title">Skrýt průzkumy</string>
|
||||
<string name="revanced_hide_surveys_summary_on">Průzkumy jsou skryté</string>
|
||||
<string name="revanced_hide_surveys_summary_off">Průzkumy jsou zobrazené</string>
|
||||
<string name="revanced_hide_ticket_shelf_title">Skrýt panel Vstupenek</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_on">Panel Vstupenek je skrytý</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_off">Panel Vstupenek je zobrazen</string>
|
||||
@@ -251,8 +251,8 @@ Pokud se Doodle v současné době zobrazuje ve vaší oblasti a toto nastavení
|
||||
<string name="revanced_hide_timed_reactions_summary_on">Reakce zobrazené po čase jsou skryty</string>
|
||||
<string name="revanced_hide_timed_reactions_summary_off">Reakce se zobrazují po čase</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_title">Skrýt „Souhrn videa generovaný pomocí AI“</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">Sekce se souhrnem videa je skrytá</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">Sekce se souhrnem videa je zobrazena</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">Sekce souhrnu videa generovaná AI je skryta</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">Sekce se souhrnem videa generovaným umělou inteligencí je zobrazena</string>
|
||||
<string name="revanced_hide_ask_section_title">Skrýt sekci Zeptat se</string>
|
||||
<string name="revanced_hide_ask_section_summary_on">Sekce Zeptat se je skrytá</string>
|
||||
<string name="revanced_hide_ask_section_summary_off">Sekce Zeptat se je zobrazena</string>
|
||||
@@ -280,19 +280,19 @@ Pokud se Doodle v současné době zobrazuje ve vaší oblasti a toto nastavení
|
||||
<string name="revanced_hide_description_components_screen_title">Popis videa</string>
|
||||
<string name="revanced_hide_description_components_screen_summary">Skrýt nebo zobrazit komponenty popisu videa</string>
|
||||
<string name="revanced_hide_filter_bar_screen_title">Lišta filtrů</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">Skrýt nebo zobrazit panel filtru v kanálech, historii, výsledcích vyhledávání a souvisejících videích</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">Skrýt nebo zobrazit lištu filtru ve zdrojích, souvisejících videích, výsledcích vyhledávání a historii sledování</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_title">Skrýt v kanálech</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_on">Skryto v kanálech</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_off">Zobrazeno v kanálech</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">Skrýt v historii</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">Skryto v historii</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">Zobrazeno v historii</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">Skrýt ve výsledcích vyhledávání</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">Skryto ve výsledcích vyhledávání</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">Zobrazeno ve výsledcích vyhledávání</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">Skrýt v souvisejících videích</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">V souvisejících videích skryto</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">V souvisejících videích zobrazeno</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">Skrýt ve výsledcích vyhledávání</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">Skryto ve výsledcích vyhledávání</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">Zobrazeno ve výsledcích vyhledávání</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">Skrýt v historii sledování</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">Skryto v historii sledování</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">Zobrazeno v historii sledování</string>
|
||||
<string name="revanced_channel_screen_title">Stránka kanálu</string>
|
||||
<string name="revanced_channel_screen_summary">Skrýt nebo zobrazit komponenty stránky kanálu</string>
|
||||
<!-- 'For You' should be translated using the same localized wording YouTube displays. -->
|
||||
@@ -315,12 +315,12 @@ Pokud se Doodle v současné době zobrazuje ve vaší oblasti a toto nastavení
|
||||
<string name="revanced_hide_visit_store_button_summary_off">Tlačítko Navštívit obchod je zobrazeno</string>
|
||||
<string name="revanced_comments_screen_title">Komentáře</string>
|
||||
<string name="revanced_comments_screen_summary">Skrýt nebo zobrazit komponenty sekce komentářů</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_title">Skrýt souhrn chatu AI</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">Souhrn chatu je skrytý</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">Souhrn chatu je zobrazen</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_title">Skrýt souhrn chatu s AI</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">Souhrn chatu s AI je skryt</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">Souhrn chatu s AI je zobrazen</string>
|
||||
<string name="revanced_hide_comments_ai_summary_title">Skrýt souhrn komentářů AI</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_on">Souhrn komentářů je skrytý</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_off">Souhrn komentářů je zobrazen</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_on">Souhrn komentářů AI je skryt</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_off">Souhrn komentářů AI je zobrazen</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_title">Skrýt pravidla kanálu</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_on">Pokyny ke kanálu jsou skryty</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_off">Pokyny ke kanálu jsou zobrazeny</string>
|
||||
@@ -419,7 +419,6 @@ Tato funkce je dostupná pouze pro starší zařízení"</string>
|
||||
<string name="revanced_hide_shopping_links_title">Skrýt nákupní odkazy</string>
|
||||
<string name="revanced_hide_shopping_links_summary_on">Nákupní odkazy v popisu videa jsou skryty</string>
|
||||
<string name="revanced_hide_shopping_links_summary_off">Nákupní odkazy v popisu videa jsou zobrazeny</string>
|
||||
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_view_products_banner_title">Skrýt banner „Zobrazit produkty“</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_on">Banner \"Zobrazit produkty\" v překrytí videa je skryt</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_off">Banner \"Zobrazit produkty\" v překrytí videa je zobrazen</string>
|
||||
@@ -453,7 +452,7 @@ Tato funkce je dostupná pouze pro starší zařízení"</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_summary_off">Dialog bude zobrazen</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">Tímto krokem neobcházíte věkové omezení. Pouze jej automaticky akceptujete.</string>
|
||||
</patch>
|
||||
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch">
|
||||
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
|
||||
<string name="revanced_disable_chapter_skip_double_tap_title">Zakázat přeskočení kapitoly dvojitým klepnutím</string>
|
||||
<string name="revanced_disable_chapter_skip_double_tap_summary_on">Dvojité klepnutí nikdy nespustí přeskočení na další/předchozí kapitolu</string>
|
||||
<string name="revanced_disable_chapter_skip_double_tap_summary_off">Dvojité klepnutí může občas spustit přeskočení na další/předchozí kapitolu</string>
|
||||
@@ -469,8 +468,15 @@ Tato funkce je dostupná pouze pro starší zařízení"</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_on">Tlačítko pro stahování otevře váš externí stahovač</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_off">Tlačítko pro stahování otevře nativní stahovač v aplikaci</string>
|
||||
<string name="revanced_external_downloader_name_title">Název balíčku stahovače</string>
|
||||
<string name="revanced_external_downloader_name_summary">Název balíčku vaší nainstalované externí aplikace pro stahování, například NewPipe nebo Seal</string>
|
||||
<string name="revanced_external_downloader_name_summary">Název balíčku vaší nainstalované externí aplikace pro stahování</string>
|
||||
<string name="revanced_external_downloader_other_item_hint">Zadejte název balíčku</string>
|
||||
<string name="revanced_external_downloader_other_item">Jiné</string>
|
||||
<string name="revanced_external_downloader_not_found_title">Aplikace není nainstalována</string>
|
||||
<string name="revanced_external_downloader_not_installed_warning">%s není nainstalováno. Prosím, nainstalujte.</string>
|
||||
<string name="revanced_external_downloader_package_not_found_warning">"Nepodařilo se najít nainstalovanou aplikaci s názvem balíčku: %s
|
||||
|
||||
Zkontrolujte, zda je název balíčku správný a aplikace je nainstalována"</string>
|
||||
<string name="revanced_external_downloader_empty_warning">Název balíčku nemůže být prázdný</string>
|
||||
</patch>
|
||||
<patch id="interaction.seekbar.disablePreciseSeekingGesturePatch">
|
||||
<string name="revanced_disable_precise_seeking_gesture_title">Zakázat gesto pro přesné hledání</string>
|
||||
@@ -730,27 +736,28 @@ Chcete-li zobrazit nabídku zvukové stopy, změňte možnost „Zfalšovat stre
|
||||
<string name="revanced_disable_rolling_number_animations_summary_off">Čísla posuvníku se animují</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.seekbar.hideSeekbarPatch">
|
||||
<string name="revanced_hide_seekbar_title">Skrýt posuvník ve video přehrávači</string>
|
||||
<string name="revanced_hide_seekbar_title">Skrýt posuvník přehrávače videa</string>
|
||||
<string name="revanced_hide_seekbar_summary_on">Posuvník ve video přehrávači je skryt</string>
|
||||
<string name="revanced_hide_seekbar_summary_off">Posuvník ve video přehrávači je zobrazen</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_title">Skrýt posuvník v miniaturách videa</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_on">Posuvník miniatur je skryt</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_off">Posuvník miniatur je zobrazen</string>
|
||||
<!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
|
||||
<string name="revanced_hide_seekbar_thumbnail_title">Skrýt posuvník miniatur videí</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_on">Posuvník miniatur videí je skryt</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_off">Posuvník miniatur videí je zobrazen</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
|
||||
<string name="revanced_shorts_player_screen_title">Přehrávač Shorts</string>
|
||||
<string name="revanced_shorts_player_screen_summary">Skrýt nebo zobrazit komponenty v přehrávači Shorts</string>
|
||||
<string name="revanced_shorts_player_screen_summary">Skrýt nebo zobrazit komponenty přehrávače Shorts</string>
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
|
||||
<string name="revanced_hide_shorts_home_title">Skrýt Shorts v kanálu Domů</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">Skryto v kanálu Domů a souvisejících videích</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">Zobrazeno v kanálu Domů a souvisejících videích</string>
|
||||
<string name="revanced_hide_shorts_search_title">Skrýt Shorts ve výsledcích vyhledávání</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">Skryté ve výsledcích vyhledávání</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">Zobrazeno ve výsledcích vyhledávání</string>
|
||||
<!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. -->
|
||||
<string name="revanced_hide_shorts_subscriptions_title">Skrýt Shorts v kanálu Odběry</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">Skryto v kanálu Odběry</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">Zobrazeno v kanálu Odběry</string>
|
||||
<string name="revanced_hide_shorts_search_title">Skrýt Shorts ve výsledcích vyhledávání</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">Skryté ve výsledcích vyhledávání</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">Zobrazeno ve výsledcích vyhledávání</string>
|
||||
<string name="revanced_hide_shorts_history_title">Skrýt Shorts z historie sledování</string>
|
||||
<string name="revanced_hide_shorts_history_summary_on">Skryté v historii sledování</string>
|
||||
<string name="revanced_hide_shorts_history_summary_off">Zobrazené v historii sledování</string>
|
||||
@@ -1190,8 +1197,6 @@ Rozložení automobilu
|
||||
To změní vzhled a funkce aplikace, ale mohou se objevit neznámé vedlejší efekty.
|
||||
|
||||
Pokud bude později vypnuta, doporučujeme vymazat data aplikace, aby se zabránilo chybám uživatelského rozhraní."</string>
|
||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_spoof_app_version_title'.
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch. -->
|
||||
<string name="revanced_spoof_app_version_target_title">Cíl napodobení verze aplikace</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_1">19.35.36 - Obnovuje staré ikony Shorts přehrávače</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_2">19.01.34 – Obnovit staré ikony navigace</string>
|
||||
@@ -1460,10 +1465,18 @@ 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_off">Tlačítko se nezobrazuje</string>
|
||||
</patch>
|
||||
<patch id="video.quality.button.videoQualityButtonPatch">
|
||||
<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_off">Tlačítko není zobrazeno.</string>
|
||||
</patch>
|
||||
<patch id="video.speed.custom.customPlaybackSpeedPatch">
|
||||
<string name="revanced_custom_speed_menu_title">Menu vlastní rychlosti přehrávání</string>
|
||||
<string name="revanced_custom_speed_menu_summary_on">Menu vlastní rychlosti se zobrazuje</string>
|
||||
<string name="revanced_custom_speed_menu_summary_off">Menu vlastní rychlosti se nezobrazuje</string>
|
||||
<string name="revanced_restore_old_speed_menu_title">Obnovit staré menu rychlosti přehrávání</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_on">Zobrazeno staré menu rychlosti</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_off">Zobrazeno moderní menu rychlosti</string>
|
||||
<string name="revanced_custom_playback_speeds_title">Vlastní rychlosti přehrávání</string>
|
||||
<string name="revanced_custom_playback_speeds_summary">Přidat nebo změnit vlastní rychlosti přehrávání</string>
|
||||
<string name="revanced_custom_playback_speeds_invalid">Vlastní rychlosti musí být menší než %s</string>
|
||||
|
||||
@@ -137,7 +137,7 @@ Du modtager ikke notifikationer om uventede hændelser."</string>
|
||||
<string name="revanced_debug_logs_disabled">Fejlsøgningslogning er deaktiveret</string>
|
||||
<string name="revanced_debug_logs_none_found">Ingen logfiler fundet</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Logfiler kopieret</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Kunne ikke eksportere logfiler: $s</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Kunne ikke eksportere logfiler: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Ryd fejlsøgningslogfiler</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Rydder alle gemte ReVanced-fejlsøgningslogfiler</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Logfiler ryddet</string>
|
||||
@@ -164,9 +164,6 @@ Du modtager ikke notifikationer om uventede hændelser."</string>
|
||||
<string name="revanced_hide_expandable_card_title">Skjul udvideligt kort</string>
|
||||
<string name="revanced_hide_expandable_card_summary_on">Udvideligt kort under videoer er skjult</string>
|
||||
<string name="revanced_hide_expandable_card_summary_off">Udvideligt kort under videoer er vist</string>
|
||||
<string name="revanced_hide_feed_survey_title">Skjul feed-undersøgelser</string>
|
||||
<string name="revanced_hide_feed_survey_summary_on">Foderundersøgelser er skjult</string>
|
||||
<string name="revanced_hide_feed_survey_summary_off">Foderundersøgelser er vist</string>
|
||||
<string name="revanced_hide_floating_microphone_button_title">Skjul flydende mikrofonknap</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_on">Svævende mikrofonknap i søgning er skjult</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_off">Flydende mikrofonknap i søgning vises</string>
|
||||
@@ -192,7 +189,7 @@ Du modtager ikke notifikationer om uventede hændelser."</string>
|
||||
<string name="revanced_hide_movies_section_summary_on">Afsnittet Film er skjult</string>
|
||||
<string name="revanced_hide_movies_section_summary_off">Afsnittet Film vises</string>
|
||||
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
|
||||
This item appear in the subscription feed for future livestreams or unreleased videos. -->
|
||||
This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
|
||||
<string name="revanced_hide_notify_me_button_title">Skjul knappen \'Underret mig\'</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_on">Giv mig besked-knap er skjult</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_off">Giv mig besked-knap vises</string>
|
||||
@@ -204,6 +201,9 @@ Du modtager ikke notifikationer om uventede hændelser."</string>
|
||||
<string name="revanced_hide_show_more_button_title">Skjul knappen \'Vis mere\'</string>
|
||||
<string name="revanced_hide_show_more_button_summary_on">Vis mere-knap i søgeresultater er skjult</string>
|
||||
<string name="revanced_hide_show_more_button_summary_off">Vis mere-knap i søgeresultater vises</string>
|
||||
<string name="revanced_hide_surveys_title">Skjul undersøgelser</string>
|
||||
<string name="revanced_hide_surveys_summary_on">Spørgeundersøgelser er skjult</string>
|
||||
<string name="revanced_hide_surveys_summary_off">Spørgeundersøgelser vises</string>
|
||||
<string name="revanced_hide_ticket_shelf_title">Skjul billetreolen</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_on">Billetreolen er skjult</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_off">Billetreolen vises</string>
|
||||
@@ -251,8 +251,8 @@ Hvis et Doodle vises i øjeblikket i din region, og denne skjuleindstilling er a
|
||||
<string name="revanced_hide_timed_reactions_summary_on">Tidsreaktioner skjules</string>
|
||||
<string name="revanced_hide_timed_reactions_summary_off">Tidsreaktioner vises</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_title">Skjul \"AI-genereret videooversigt\"</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">Videooversigtssektionen er skjult</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">Videooversigtssektionen vises</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">AI-genereret videooversigt er skjult</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">AI-genereret videooversigtssektion vises</string>
|
||||
<string name="revanced_hide_ask_section_title">Skjul Spørg</string>
|
||||
<string name="revanced_hide_ask_section_summary_on">Spørgsmål sektionen er skjult</string>
|
||||
<string name="revanced_hide_ask_section_summary_off">Spørgsmål sektionen vises</string>
|
||||
@@ -280,19 +280,19 @@ Hvis et Doodle vises i øjeblikket i din region, og denne skjuleindstilling er a
|
||||
<string name="revanced_hide_description_components_screen_title">Video beskrivelse</string>
|
||||
<string name="revanced_hide_description_components_screen_summary">Skjul eller vis komponenter til videobeskrivelse</string>
|
||||
<string name="revanced_hide_filter_bar_screen_title">Filtrer bjælke</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">Skjul eller vis filterlinjen i feeds, historik, søgeresultater og relaterede videoer</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">Skjul eller vis filterlinjen i feeds, relaterede videoer, søgeresultater og seerhistorik</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_title">Skjul i feeds</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_on">Skjult i feeds</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_off">Vist i feeds</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">Skjul i historik</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">Skjult i historik</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">Vist i historik</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">Skjul i søgeresultater</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">Skjult i søgeresultater</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">Vises i søgeresultater</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">Skjul i relaterede videoer</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">Skjult i relaterede videoer</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">Vist i relaterede videoer</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">Skjul i søgeresultater</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">Skjult i søgeresultater</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">Vises i søgeresultater</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">Skjul i seerhistorik</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">Skjult i seerhistorik</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">Vist i seerhistorik</string>
|
||||
<string name="revanced_channel_screen_title">Kanalside</string>
|
||||
<string name="revanced_channel_screen_summary">Skjul eller vis kanalsidekomponenter</string>
|
||||
<!-- 'For You' should be translated using the same localized wording YouTube displays. -->
|
||||
@@ -315,12 +315,12 @@ Hvis et Doodle vises i øjeblikket i din region, og denne skjuleindstilling er a
|
||||
<string name="revanced_hide_visit_store_button_summary_off">Besøg butik-knap er vist</string>
|
||||
<string name="revanced_comments_screen_title">Kommentarer</string>
|
||||
<string name="revanced_comments_screen_summary">Skjul eller vis kommentarer sektion komponenter</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_title">Skjul AI Chat-oversigt</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">Chat-oversigt er skjult</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">Chat-oversigt er vist</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_title">Skjul AI-chatsammendrag</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">AI-chatsammendrag er skjult</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">AI-chatsammendrag vises</string>
|
||||
<string name="revanced_hide_comments_ai_summary_title">Skjul AI Kommentar-oversigt</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_on">Kommentar-oversigt er skjult</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_off">Kommentar-oversigt er vist</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_on">AI-kommentarsammendrag er skjult</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_off">AI-kommentarsammendrag vises</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_title">Skjul kanalretningslinjer</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_on">Kanalretningslinjer er skjult</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_off">Kanalretningslinjer er vist</string>
|
||||
@@ -419,7 +419,6 @@ Denne funktion er kun tilgængelig for ældre enheder"</string>
|
||||
<string name="revanced_hide_shopping_links_title">Skjul shopping-links</string>
|
||||
<string name="revanced_hide_shopping_links_summary_on">Shoppinglinks i videobeskrivelse er skjult</string>
|
||||
<string name="revanced_hide_shopping_links_summary_off">Shoppinglinks i videobeskrivelsen vises</string>
|
||||
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_view_products_banner_title">Skjul banneret \"Se produkter\"</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_on">Se produkter-banner i videooverlay er skjult</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_off">Se produkter-banner i videooverlay vises</string>
|
||||
@@ -453,7 +452,7 @@ Denne funktion er kun tilgængelig for ældre enheder"</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_summary_off">Dialog vil blive vist</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">Dette går ikke uden om aldersbegrænsningen. Det accepterer bare det automatisk.</string>
|
||||
</patch>
|
||||
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch">
|
||||
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
|
||||
<string name="revanced_disable_chapter_skip_double_tap_title">Deaktiver dobbeltklik kapitelspring</string>
|
||||
<string name="revanced_disable_chapter_skip_double_tap_summary_on">Dobbeltklik kan aldrig udløse et spring til næste/forrige kapitel</string>
|
||||
<string name="revanced_disable_chapter_skip_double_tap_summary_off">Dobbeltklik kan lejlighedsvis udløse et spring til næste/forrige kapitel</string>
|
||||
@@ -469,8 +468,15 @@ Denne funktion er kun tilgængelig for ældre enheder"</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_on">Download-knappen åbner din eksterne downloader</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_off">Download-knappen åbner den indfødte in-app downloader</string>
|
||||
<string name="revanced_external_downloader_name_title">Downloader pakkenavn</string>
|
||||
<string name="revanced_external_downloader_name_summary">Pakkenavn på din installerede eksterne downloader-app, såsom NewPipe eller Seal</string>
|
||||
<string name="revanced_external_downloader_name_summary">Pakkenavn på din installerede eksterne download-app</string>
|
||||
<string name="revanced_external_downloader_other_item_hint">Indtast pakkenavnet</string>
|
||||
<string name="revanced_external_downloader_other_item">Andet</string>
|
||||
<string name="revanced_external_downloader_not_found_title">Appen er ikke installeret</string>
|
||||
<string name="revanced_external_downloader_not_installed_warning">%s er ikke installeret. Installér den.</string>
|
||||
<string name="revanced_external_downloader_package_not_found_warning">"Kunne ikke finde installeret app med pakkenavn: %s
|
||||
|
||||
Kontrollér, at pakkenavnet er korrekt, og at appen er installeret"</string>
|
||||
<string name="revanced_external_downloader_empty_warning">Pakkenavnet må ikke være tomt</string>
|
||||
</patch>
|
||||
<patch id="interaction.seekbar.disablePreciseSeekingGesturePatch">
|
||||
<string name="revanced_disable_precise_seeking_gesture_title">Deaktivér præcis søgemåde</string>
|
||||
@@ -730,27 +736,28 @@ For at vise lydspormenuen skal du ændre \"Spoof videostream\" til iOS TV"</stri
|
||||
<string name="revanced_disable_rolling_number_animations_summary_off">Rullende numre er animeret</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.seekbar.hideSeekbarPatch">
|
||||
<string name="revanced_hide_seekbar_title">Skjul søgelinje i videoafspiller</string>
|
||||
<string name="revanced_hide_seekbar_title">Skjul videoafspillerens søgelinje</string>
|
||||
<string name="revanced_hide_seekbar_summary_on">Videoafspillerens søgelinje er skjult</string>
|
||||
<string name="revanced_hide_seekbar_summary_off">Videoafspillerens søgelinje vises</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_title">Skjul søgelinje i videominiaturer</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_on">Miniaturesøgelinjen er skjult</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_off">Miniaturesøgelinjen vises</string>
|
||||
<!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
|
||||
<string name="revanced_hide_seekbar_thumbnail_title">Skjul video-miniaturebilledernes søgelinje</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_on">Video-miniaturebilledernes søgelinje er skjult</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_off">Video-miniaturebilledernes søgelinje vises</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
|
||||
<string name="revanced_shorts_player_screen_title">Shorts-afspiller</string>
|
||||
<string name="revanced_shorts_player_screen_summary">Skjul eller vis komponenter i Shorts-afspilleren</string>
|
||||
<string name="revanced_shorts_player_screen_summary">Skjul eller vis Shorts-afspillerkomponenter</string>
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
|
||||
<string name="revanced_hide_shorts_home_title">Skjul Shorts i \'Hjem\'-feed</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">Skjult i \'Hjem\'-feed og relaterede videoer</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">Vises i \'Hjem\'-feed og relaterede videoer</string>
|
||||
<string name="revanced_hide_shorts_search_title">Skjul Shorts i søgeresultater</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">Skjult i søgeresultater</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">Vises i søgeresultater</string>
|
||||
<!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. -->
|
||||
<string name="revanced_hide_shorts_subscriptions_title">Skjul Shorts i \'Abonnementer\'-feed</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">Skjult i \'Abonnementer\'-feed</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">Vises i \'Abonnementer\'-feed</string>
|
||||
<string name="revanced_hide_shorts_search_title">Skjul Shorts i søgeresultater</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">Skjult i søgeresultater</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">Vises i søgeresultater</string>
|
||||
<string name="revanced_hide_shorts_history_title">Skjul shorts i historik</string>
|
||||
<string name="revanced_hide_shorts_history_summary_on">Skjult i historikken</string>
|
||||
<string name="revanced_hide_shorts_history_summary_off">Vises i historik</string>
|
||||
@@ -1192,8 +1199,6 @@ Automotive-layout
|
||||
Dette ændrer appens udseende og funktioner, men ukendte bivirkninger kan forekomme.
|
||||
|
||||
Hvis det senere slås fra, anbefales det at rydde app-dataene for at forhindre UI-fejl."</string>
|
||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_spoof_app_version_title'.
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch. -->
|
||||
<string name="revanced_spoof_app_version_target_title">Spoof app version mål</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_1">19.35.36 - Gendan gamle Shorts player ikoner</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_2">19.01.34 - Gendan gamle navigationsikoner</string>
|
||||
@@ -1462,10 +1467,18 @@ 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_off">Knap vises ikke</string>
|
||||
</patch>
|
||||
<patch id="video.quality.button.videoQualityButtonPatch">
|
||||
<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_off">Knappen vises ikke</string>
|
||||
</patch>
|
||||
<patch id="video.speed.custom.customPlaybackSpeedPatch">
|
||||
<string name="revanced_custom_speed_menu_title">Tilpasset afspilningshastighed menu</string>
|
||||
<string name="revanced_custom_speed_menu_summary_on">Tilpasset hastighed menu er vist</string>
|
||||
<string name="revanced_custom_speed_menu_summary_off">Brugerdefineret hastighedsmenu vises ikke</string>
|
||||
<string name="revanced_restore_old_speed_menu_title">Gendan gammel afspilningshastighedsmenu</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_on">Gammel hastighedsmenu vises</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_off">Moderne hastighedsmenu vises</string>
|
||||
<string name="revanced_custom_playback_speeds_title">Tilpasset afspilningshastighed</string>
|
||||
<string name="revanced_custom_playback_speeds_summary">Tilføj eller ændr den brugerdefinerede afspilningshastighed</string>
|
||||
<string name="revanced_custom_playback_speeds_invalid">Brugerdefinerede hastigheder skal være mindre end %s</string>
|
||||
|
||||
@@ -72,7 +72,9 @@ Um neue Sprachen zu übersetzen, besuchen Sie translate.revanced.app"</string>
|
||||
<string name="gms_core_toast_not_installed_message">MicroG GmsCore ist nicht installiert. Installieren Sie es.</string>
|
||||
<string name="gms_core_dialog_title">Aktion notwendig</string>
|
||||
<string name="gms_core_dialog_not_whitelisted_not_allowed_in_background_message">"MicroG GmsCore hat keine Berechtigung, im Hintergrund zu laufen.
|
||||
Folgen Sie der Anleitung \"Meine App nicht beenden\" für Ihr Telefon und wenden Sie die Anweisungen auf Ihre MicroG-Installation an.
|
||||
|
||||
Folgen Sie der Anleitung \"Don't kill my app\" für Ihr Gerät und wenden Sie die Anweisungen auf Ihre MicroG-Installation an.
|
||||
|
||||
Dies ist erforderlich, damit die App funktioniert."</string>
|
||||
<string name="gms_core_dialog_open_website_text">Website öffnen</string>
|
||||
<string name="gms_core_dialog_not_whitelisted_using_battery_optimizations_message">"Die Batterieoptimierung von MicroG GmsCore muss deaktiviert werden, um Probleme zu vermeiden.
|
||||
@@ -85,7 +87,7 @@ Tippen Sie auf die Schaltfläche \"Fortfahren\" und erlauben Sie die Optimierung
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
<string name="revanced_settings_screen_00_about_title">Über</string>
|
||||
<string name="revanced_settings_screen_01_ads_title">Werbung</string>
|
||||
<string name="revanced_settings_screen_02_alt_thumbnails_title">Alternative Miniaturbilder</string>
|
||||
<string name="revanced_settings_screen_02_alt_thumbnails_title">Alternative Thumbnails</string>
|
||||
<string name="revanced_settings_screen_03_feed_title">Feed</string>
|
||||
<string name="revanced_settings_screen_04_general_title">Allgemein</string>
|
||||
<string name="revanced_settings_screen_05_player_title">Spieler</string>
|
||||
@@ -133,7 +135,7 @@ Sie werden nicht über unerwartete Ereignisse informiert."</string>
|
||||
<string name="revanced_debug_logs_disabled">Debug-Protokollierung ist deaktiviert</string>
|
||||
<string name="revanced_debug_logs_none_found">Keine Protokolle gefunden</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Protokolle kopiert</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Fehler beim Exportieren von Protokollen: $s</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Fehler beim Exportieren der Protokolle: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Debug-Protokolle löschen</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Löscht alle gespeicherten ReVanced-Debug-Protokolle</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Protokolle gelöscht</string>
|
||||
@@ -160,9 +162,6 @@ Sie werden nicht über unerwartete Ereignisse informiert."</string>
|
||||
<string name="revanced_hide_expandable_card_title">Ausklappbare Karte ausblenden</string>
|
||||
<string name="revanced_hide_expandable_card_summary_on">Ausklappbare Karte unter Videos ist ausgeblendet</string>
|
||||
<string name="revanced_hide_expandable_card_summary_off">Ausklappbare Karte unter Videos ist angezeigt</string>
|
||||
<string name="revanced_hide_feed_survey_title">Feed-Umfragen ausblenden</string>
|
||||
<string name="revanced_hide_feed_survey_summary_on">Feed-Umfragen sind ausgeblendet</string>
|
||||
<string name="revanced_hide_feed_survey_summary_off">Feed-Umfragen werden angezeigt</string>
|
||||
<string name="revanced_hide_floating_microphone_button_title">Schwebende Mikrofon-Taste ausblenden</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_on">Schwebende Mikrofonschaltfläche in der Suche ist ausgeblendet</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_off">Der schwebende Mikrofon-Button in der Suche wird angezeigt</string>
|
||||
@@ -188,7 +187,7 @@ Sie werden nicht über unerwartete Ereignisse informiert."</string>
|
||||
<string name="revanced_hide_movies_section_summary_on">Film Abschnitt ist ausgeblendet</string>
|
||||
<string name="revanced_hide_movies_section_summary_off">Film Bereich wird angezeigt</string>
|
||||
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
|
||||
This item appear in the subscription feed for future livestreams or unreleased videos. -->
|
||||
This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
|
||||
<string name="revanced_hide_notify_me_button_title">\'Benachrichtigungen\' Button ausblenden</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_on">Schaltfläche \"Benachrichtige mich\" ist ausgeblendet</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_off">Schaltfläche \"Benachrichtige mich\" wird angezeigt</string>
|
||||
@@ -200,6 +199,9 @@ Sie werden nicht über unerwartete Ereignisse informiert."</string>
|
||||
<string name="revanced_hide_show_more_button_title">\'Mehr anzeigen\' Button ausblenden</string>
|
||||
<string name="revanced_hide_show_more_button_summary_on">Schaltfläche \"Mehr anzeigen\" in den Suchergebnissen ist ausgeblendet</string>
|
||||
<string name="revanced_hide_show_more_button_summary_off">Schaltfläche \"Mehr anzeigen\" in den Suchergebnissen wird angezeigt</string>
|
||||
<string name="revanced_hide_surveys_title">Umfragen ausblenden</string>
|
||||
<string name="revanced_hide_surveys_summary_on">Umfragen sind ausgeblendet</string>
|
||||
<string name="revanced_hide_surveys_summary_off">Umfragen werden angezeigt</string>
|
||||
<string name="revanced_hide_ticket_shelf_title">Ticket-Reihe ausblenden</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_on">Ticket-Reihe ist ausgeblendet</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_off">Ticket-Reihe wird angezeigt</string>
|
||||
@@ -246,8 +248,8 @@ Wenn ein Doodle zurzeit in Ihrer Region angezeigt wird und diese Einstellung zum
|
||||
<string name="revanced_hide_timed_reactions_summary_on">Zeitgesteuerte Reaktionen sind ausgeblendet</string>
|
||||
<string name="revanced_hide_timed_reactions_summary_off">Zeitgesteuerte Reaktionen werden angezeigt</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_title">\'KI-generierte Videozusammenfassung\' ausblenden</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">Videozusammenfassungsbereich ist ausgeblendet</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">Videozusammenfassungsbereich wird angezeigt</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">KI-generierter Videozusammenfassungsbereich ist ausgeblendet</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">Abschnitt mit KI-generierter Videozusammenfassung wird angezeigt</string>
|
||||
<string name="revanced_hide_ask_section_title">Ask ausblenden</string>
|
||||
<string name="revanced_hide_ask_section_summary_on">Ask Abschnitt ist ausgeblendet</string>
|
||||
<string name="revanced_hide_ask_section_summary_off">Ask Abschnitt wird angezeigt</string>
|
||||
@@ -275,19 +277,19 @@ Wenn ein Doodle zurzeit in Ihrer Region angezeigt wird und diese Einstellung zum
|
||||
<string name="revanced_hide_description_components_screen_title">Videobeschreibung</string>
|
||||
<string name="revanced_hide_description_components_screen_summary">Komponenten der Videobeschreibung ausblenden oder anzeigen</string>
|
||||
<string name="revanced_hide_filter_bar_screen_title">Filterleiste</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">Filterleiste in den Feeds, im Verlauf, in den Suchergebnissen und in ähnlichen Videos ein- oder ausblenden</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">Filterleiste in Feeds, ähnlichen Videos, Suchergebnissen und im Wiedergabeverlauf aus- oder einblenden</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_title">In Feeds ausblenden</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_on">In Feeds ausgeblendet</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_off">In Feeds angezeigt</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">Im Verlauf ausblenden</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">Im Verlauf ausgeblendet</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">Im Verlauf angezeigt</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">In Suchergebnissen ausblenden</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">In Suchergebnissen versteckt</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">In den Suchergebnissen angezeigt</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">In verwandten Videos ausblenden</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">Versteckt in verwandten Videos</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">In verwandten Videos angezeigt</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">In Suchergebnissen ausblenden</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">In Suchergebnissen versteckt</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">In den Suchergebnissen angezeigt</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">Im Wiedergabeverlauf ausblenden</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">Im Wiedergabeverlauf ausgeblendet</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">Im Wiedergabeverlauf angezeigt</string>
|
||||
<string name="revanced_channel_screen_title">Kanalseite</string>
|
||||
<string name="revanced_channel_screen_summary">Kanalseitenkomponenten ausblenden oder anzeigen</string>
|
||||
<!-- 'For You' should be translated using the same localized wording YouTube displays. -->
|
||||
@@ -311,11 +313,11 @@ Wenn ein Doodle zurzeit in Ihrer Region angezeigt wird und diese Einstellung zum
|
||||
<string name="revanced_comments_screen_title">Kommentare</string>
|
||||
<string name="revanced_comments_screen_summary">Komponenten der Kommentar-Sektion ausblenden oder anzeigen</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_title">KI-Chat-Zusammenfassung ausblenden</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">Chat-Übersichtsanzeige ist ausgeblendet</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">Die Chat-Zusammenfassung wird angezeigt</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">KI-Chat-Zusammenfassung ist ausgeblendet</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">KI-Chat-Zusammenfassung ist eingeblendet</string>
|
||||
<string name="revanced_hide_comments_ai_summary_title">KI-Kommentarübersicht ausblenden</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_on">Kommentarübersicht ist ausgeblendet</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_off">Kommentarübersicht wird angezeigt</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_on">KI-Kommentar-Zusammenfassung ist ausgeblendet</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_off">KI-Kommentar-Zusammenfassung ist eingeblendet</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_title">Kanalrichtlinien ausblenden</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_on">Kanalrichtlinien sind ausgeblendet</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_off">Kanalrichtlinien werden angezeigt</string>
|
||||
@@ -414,7 +416,6 @@ Diese Funktion ist nur für ältere Geräte verfügbar"</string>
|
||||
<string name="revanced_hide_shopping_links_title">Shopping-Links ausblenden</string>
|
||||
<string name="revanced_hide_shopping_links_summary_on">Shopping-Links in der Videobeschreibung sind ausgeblendet</string>
|
||||
<string name="revanced_hide_shopping_links_summary_off">Shopping-Links in der Videobeschreibung werden angezeigt</string>
|
||||
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_view_products_banner_title">„Produkte ansehen“-Banner ausblenden</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_on">Produkte anzeigen-Banner im Video-Overlay ist ausgeblendet</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_off">Produkte anzeigen-Banner im Video-Overlay wird angezeigt</string>
|
||||
@@ -448,7 +449,7 @@ Diese Funktion ist nur für ältere Geräte verfügbar"</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_summary_off">Dialog wird angezeigt</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">Dies umgeht nicht die Altersbeschränkung, sondern akzeptiert sie nur automatisch.</string>
|
||||
</patch>
|
||||
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch">
|
||||
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
|
||||
<string name="revanced_disable_chapter_skip_double_tap_title">Doppeltippen zum Kapitelüberspringen deaktivieren</string>
|
||||
<string name="revanced_disable_chapter_skip_double_tap_summary_on">Doppeltippen kann niemals ein Überspringen zum nächsten/vorherigen Kapitel auslösen</string>
|
||||
<string name="revanced_disable_chapter_skip_double_tap_summary_off">Doppeltippen kann gelegentlich ein Überspringen zum nächsten/vorherigen Kapitel auslösen</string>
|
||||
@@ -464,8 +465,15 @@ Diese Funktion ist nur für ältere Geräte verfügbar"</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_on">Download-Button öffnet den externen Downloader</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_off">Download-Button öffnet den nativen In-App-Downloader</string>
|
||||
<string name="revanced_external_downloader_name_title">Paketname des Downloaders</string>
|
||||
<string name="revanced_external_downloader_name_summary">Paketname deiner installierten externen Downloader-App wie NewPipe oder Siegel</string>
|
||||
<string name="revanced_external_downloader_name_summary">Paketname Ihrer installierten externen Downloader-App</string>
|
||||
<string name="revanced_external_downloader_other_item_hint">Paketnamen eingeben</string>
|
||||
<string name="revanced_external_downloader_other_item">Andere</string>
|
||||
<string name="revanced_external_downloader_not_found_title">App nicht installiert</string>
|
||||
<string name="revanced_external_downloader_not_installed_warning">%s ist nicht installiert. Installier es.</string>
|
||||
<string name="revanced_external_downloader_package_not_found_warning">"Installierte App mit Paketnamen nicht gefunden: %s
|
||||
|
||||
Stellen Sie sicher, dass der Paketname korrekt ist und die App installiert ist"</string>
|
||||
<string name="revanced_external_downloader_empty_warning">Der Paketname darf nicht leer sein</string>
|
||||
</patch>
|
||||
<patch id="interaction.seekbar.disablePreciseSeekingGesturePatch">
|
||||
<string name="revanced_disable_precise_seeking_gesture_title">Genaue Suchgeste deaktivieren</string>
|
||||
@@ -723,27 +731,28 @@ Um das Audiotrack-Menü anzuzeigen, ändere \"Video-Streams fälschen\" zu iOS T
|
||||
<string name="revanced_disable_rolling_number_animations_summary_off">Rollende Zahlen sind animiert</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.seekbar.hideSeekbarPatch">
|
||||
<string name="revanced_hide_seekbar_title">Suchleiste im Video-Player ausblenden</string>
|
||||
<string name="revanced_hide_seekbar_title">Video-Player-Suchleiste ausblenden</string>
|
||||
<string name="revanced_hide_seekbar_summary_on">Video-Player-Suchleiste ist ausgeblendet</string>
|
||||
<string name="revanced_hide_seekbar_summary_off">Suchleiste für Video-Player wird angezeigt</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_title">Suchleiste in Video-Thumbnails ausblenden</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_on">Miniaturansicht-Suchleiste ist ausgeblendet</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_off">Miniaturansicht-Suchleiste wird angezeigt</string>
|
||||
<!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
|
||||
<string name="revanced_hide_seekbar_thumbnail_title">Suchleiste für Video-Thumbnails ausblenden</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_on">Suchleiste für Video-Thumbnails ist ausgeblendet</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_off">Suchleiste für Video-Thumbnails ist eingeblendet</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.shorts.hideShortsComponentsResourcePatch">
|
||||
<string name="revanced_shorts_player_screen_title">Shorts Spieler</string>
|
||||
<string name="revanced_shorts_player_screen_summary">Komponenten im Shorts Spieler ausblenden oder anzeigen</string>
|
||||
<string name="revanced_shorts_player_screen_summary">Shorts-Player-Komponenten aus- oder einblenden</string>
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
|
||||
<string name="revanced_hide_shorts_home_title">Shorts im Startseiten-Feed ausblenden</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">Im Startseiten-Feed und verwandten Videos ausgeblendet</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">Im Startseiten-Feed und verwandten Videos angezeigt</string>
|
||||
<string name="revanced_hide_shorts_search_title">Shorts in den Suchergebnissen ausblenden</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">In Suchergebnissen versteckt</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">In den Suchergebnissen angezeigt</string>
|
||||
<!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. -->
|
||||
<string name="revanced_hide_shorts_subscriptions_title">Shorts im Abos-Feed ausblenden</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">Im Abos-Feed ausgeblendet</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">Im Abos-Feed angezeigt</string>
|
||||
<string name="revanced_hide_shorts_search_title">Shorts in den Suchergebnissen ausblenden</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">In Suchergebnissen versteckt</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">In den Suchergebnissen angezeigt</string>
|
||||
<string name="revanced_hide_shorts_history_title">Shorts im Verlauf verstecken</string>
|
||||
<string name="revanced_hide_shorts_history_summary_on">Im Verlauf versteckt</string>
|
||||
<string name="revanced_hide_shorts_history_summary_off">Im Verlauf angezeigt</string>
|
||||
@@ -1183,8 +1192,6 @@ Automotive-Layout
|
||||
Dadurch ändert sich das Erscheinungsbild und die Funktionen der App, es können jedoch unbekannte Nebeneffekte auftreten.
|
||||
|
||||
Wenn Sie die Funktion später deaktivieren, wird empfohlen, die App-Daten zu löschen, um UI-Fehler zu vermeiden."</string>
|
||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_spoof_app_version_title'.
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch. -->
|
||||
<string name="revanced_spoof_app_version_target_title">Spoof-App-Versionsziel</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_1">19.35.36 - Alte Shorts Spielersymbole wiederherstellen</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_2">19.01.34 - Alte Navigations-Symbole wiederherstellen</string>
|
||||
@@ -1453,10 +1460,18 @@ 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_off">Button wird nicht angezeigt</string>
|
||||
</patch>
|
||||
<patch id="video.quality.button.videoQualityButtonPatch">
|
||||
<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_off">Schaltfläche wird nicht angezeigt</string>
|
||||
</patch>
|
||||
<patch id="video.speed.custom.customPlaybackSpeedPatch">
|
||||
<string name="revanced_custom_speed_menu_title">Benutzerdefiniertes Wiedergabegeschwindigkeitsmenü</string>
|
||||
<string name="revanced_custom_speed_menu_summary_on">Benutzerdefiniertes Geschwindigkeitsmenü wird angezeigt</string>
|
||||
<string name="revanced_custom_speed_menu_summary_off">Benutzerdefiniertes Geschwindigkeitsmenü wird nicht angezeigt</string>
|
||||
<string name="revanced_restore_old_speed_menu_title">Altes Wiedergabegeschwindigkeitsmenü wiederherstellen</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_on">Altes Geschwindigkeitsmenü wird angezeigt</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_off">Modernes Geschwindigkeitsmenü wird angezeigt</string>
|
||||
<string name="revanced_custom_playback_speeds_title">Benutzerdefinierte Wiedergabegeschwindigkeiten</string>
|
||||
<string name="revanced_custom_playback_speeds_summary">Hinzufügen oder Ändern der benutzerdefinierten Wiedergabegeschwindigkeit</string>
|
||||
<string name="revanced_custom_playback_speeds_invalid">Benutzerdefinierte Geschwindigkeiten müssen kleiner als %s sein</string>
|
||||
|
||||
@@ -75,7 +75,7 @@ Second \"item\" text"</string>
|
||||
|
||||
Ακολουθήστε τον οδηγό \"Don't kill my app\" για το τηλέφωνό σας και εφαρμόστε τις οδηγίες στο MicroG.
|
||||
|
||||
Αυτό είναι απαραίτητο για τη λειτουργία της εφαρμογής."</string>
|
||||
Αυτό είναι απαραίτητο για τη σωστή λειτουργία της εφαρμογής."</string>
|
||||
<string name="gms_core_dialog_open_website_text">Άνοιγμα ιστοσελίδας</string>
|
||||
<string name="gms_core_dialog_not_whitelisted_using_battery_optimizations_message">"Οι βελτιστοποιήσεις μπαταρίας πρέπει να απενεργοποιηθούν για το MicroG GmsCore ώστε να αποφευχθούν προβλήματα.
|
||||
|
||||
@@ -137,7 +137,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_debug_logs_disabled">Η καταγραφή εντοπισμού σφαλμάτων είναι απενεργοποιημένη</string>
|
||||
<string name="revanced_debug_logs_none_found">Δεν βρέθηκαν αρχεία καταγραφής</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Τα αρχεία καταγραφής αντιγράφηκαν</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Αποτυχία εξαγωγής αρχείων καταγραφής: $s</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Αποτυχία εξαγωγής αρχείων καταγραφής: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Εκκαθάριση αρχείων καταγραφής εντοπισμού σφαλμάτων</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Εκκαθάριση όλων των αποθηκευμένων αρχειών καταγραφής εντοπισμού σφαλμάτων ReVanced</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Τα αρχεία καταγραφής εκκαθαρίστηκαν</string>
|
||||
@@ -164,9 +164,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_expandable_card_title">Επεκτάσιμο πλαίσιο κάτω από τα βίντεο</string>
|
||||
<string name="revanced_hide_expandable_card_summary_on">Κρυμμένο</string>
|
||||
<string name="revanced_hide_expandable_card_summary_off">Εμφανίζεται</string>
|
||||
<string name="revanced_hide_feed_survey_title">Έρευνες στη ροή</string>
|
||||
<string name="revanced_hide_feed_survey_summary_on">Κρυμμένες</string>
|
||||
<string name="revanced_hide_feed_survey_summary_off">Εμφανίζονται</string>
|
||||
<string name="revanced_hide_floating_microphone_button_title">Αιωρούμενο κουμπί μικροφώνου στην αναζήτηση</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_on">Κρυμμένο</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_off">Εμφανίζεται</string>
|
||||
@@ -194,7 +191,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_movies_section_summary_on">Κρυμμένη</string>
|
||||
<string name="revanced_hide_movies_section_summary_off">Εμφανίζεται</string>
|
||||
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
|
||||
This item appear in the subscription feed for future livestreams or unreleased videos. -->
|
||||
This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
|
||||
<string name="revanced_hide_notify_me_button_title">Κουμπί «Να λαμβάνω ειδοποιήσεις»</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_on">Κρυμμένο</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_off">Εμφανίζεται</string>
|
||||
@@ -206,6 +203,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_show_more_button_title">Κουμπί «Εμφάνιση περισσότερων»</string>
|
||||
<string name="revanced_hide_show_more_button_summary_on">Κρυμμένο\n\nΑφορά το κουμπί «Εμφάνιση περισσότερων» στα αποτελέσματα αναζήτησης</string>
|
||||
<string name="revanced_hide_show_more_button_summary_off">Εμφανίζεται\n\nΑφορά το κουμπί «Εμφάνιση περισσότερων» στα αποτελέσματα αναζήτησης</string>
|
||||
<string name="revanced_hide_surveys_title">Έρευνες</string>
|
||||
<string name="revanced_hide_surveys_summary_on">Κρυμμένες</string>
|
||||
<string name="revanced_hide_surveys_summary_off">Εμφανίζονται</string>
|
||||
<string name="revanced_hide_ticket_shelf_title">Ενότητα εισιτηρίων</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_on">Κρυμμένη</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_off">Εμφανίζεται</string>
|
||||
@@ -243,7 +243,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_quick_actions_title">Γρήγορες ενέργειες</string>
|
||||
<string name="revanced_hide_quick_actions_summary_on">Κρυμμένες</string>
|
||||
<string name="revanced_hide_quick_actions_summary_off">Εμφανίζονται</string>
|
||||
<string name="revanced_hide_related_videos_title">Σχετικά βίντεο στις γρήγορες ενέργειες</string>
|
||||
<string name="revanced_hide_related_videos_title">Περισσότερα βίντεο στις γρήγορες ενέργειες</string>
|
||||
<string name="revanced_hide_related_videos_summary_on">Κρυμμένα</string>
|
||||
<string name="revanced_hide_related_videos_summary_off">Εμφανίζονται</string>
|
||||
<string name="revanced_hide_subscribers_community_guidelines_title">Οδηγίες συνδρομητών</string>
|
||||
@@ -282,19 +282,19 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_description_components_screen_title">Περιγραφή βίντεο</string>
|
||||
<string name="revanced_hide_description_components_screen_summary">Απόκρυψη ή εμφάνιση στοιχείων περιγραφής βίντεο</string>
|
||||
<string name="revanced_hide_filter_bar_screen_title">Γραμμή φίλτρων</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">Απόκρυψη ή εμφάνιση της γραμμής φίλτρων στις ροές, στο ιστορικό, στα αποτελέσματα αναζήτησης και στα σχετικά βίντεο</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_title">Απόκρυψη στις ροές</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">Απόκρυψη ή εμφάνιση της γραμμής φίλτρων στις ροές, στα σχετικά βίντεο, στα αποτελέσματα αναζήτησης και στο ιστορικό παρακολούθησης</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_title">Γραμμή φίλτρων στις ροές</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_on">Κρυμμένη</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_off">Εμφανίζεται</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">Απόκρυψη στο ιστορικό</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">Κρυμμένη</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">Εμφανίζεται</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">Απόκρυψη στα αποτελέσματα αναζήτησης</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">Κρυμμένη</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">Εμφανίζεται</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">Απόκρυψη στα σχετικά βίντεο</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">Γραμμή φίλτρων στα σχετικά βίντεο</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">Κρυμμένη</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">Εμφανίζεται</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">Γραμμή φίλτρων στα αποτελέσματα αναζήτησης</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">Κρυμμένη</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">Εμφανίζεται</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">Γραμμή φίλτρων στο ιστορικό παρακολούθησης</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">Κρυμμένη</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">Εμφανίζεται</string>
|
||||
<string name="revanced_channel_screen_title">Σελίδα καναλιού</string>
|
||||
<string name="revanced_channel_screen_summary">Απόκρυψη ή εμφάνιση στοιχείων της σελίδας καναλιού</string>
|
||||
<!-- 'For You' should be translated using the same localized wording YouTube displays. -->
|
||||
@@ -312,12 +312,12 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_visit_community_button_summary_on">Κρυμμένο</string>
|
||||
<string name="revanced_hide_visit_community_button_summary_off">Εμφανίζεται</string>
|
||||
<!-- 'Visit store' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_visit_store_button_title">Κουμπί «Επίσκεψη στο κατάστημα» στη σελίδα καναλιού</string>
|
||||
<string name="revanced_hide_visit_store_button_title">Κουμπί «Επίσκεψη στο κατάστημα»</string>
|
||||
<string name="revanced_hide_visit_store_button_summary_on">Κρυμμένο</string>
|
||||
<string name="revanced_hide_visit_store_button_summary_off">Εμφανίζεται</string>
|
||||
<string name="revanced_comments_screen_title">Σχόλια</string>
|
||||
<string name="revanced_comments_screen_summary">Απόκρυψη ή εμφάνιση στοιχείων στα σχόλια</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_title">Σύνοψη συνομιλίας που δημιουργήθηκε από AI</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_title">Σύνοψη συζήτησης που δημιουργήθηκε από AI</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">Κρυμμένη</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">Εμφανίζεται</string>
|
||||
<string name="revanced_hide_comments_ai_summary_title">Σύνοψη σχολίων που δημιουργήθηκε από AI</string>
|
||||
@@ -358,9 +358,9 @@ Second \"item\" text"</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_summary">Απόκρυψη βίντεο ροής και αναζήτησης χρησιμοποιώντας φίλτρα λέξεων-κλειδιών</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_off">Τα βίντεο στην αρχική σελίδα δε φιλτράρονται από λέξεις-κλειδιά</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_off">Τα βίντεο στην αρχική ροή δε φιλτράρονται από λέξεις-κλειδιά</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_off">Τα αποτελέσματα αναζήτησης δε φιλτράρονται από λέξεις-κλειδιά</string>
|
||||
@@ -379,8 +379,8 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_keyword_content_about_summary">"Οι καρτέλες «Αρχική», «Εγγραφές» και τα αποτελέσματα αναζήτησης φιλτράρονται για απόκρυψη περιεχομένου που ταιριάζει με τις λέξεις-κλειδιά
|
||||
|
||||
Περιορισμοί:
|
||||
• Τα Shorts δεν γίνεται να κρύβονται με βάση το όνομα καναλιού
|
||||
• Κάποια στοιχεία UI ενδέχεται να μην κρύβονται
|
||||
• Δεν γίνεται απόκρυψη των Shorts με βάση το όνομα καναλιού
|
||||
• Κάποια στοιχεία UI ενδέχεται να μην είναι κρυμμένα
|
||||
• Η αναζήτηση για μια λέξη-κλειδί ενδέχεται να μην εμφανίζει κανένα αποτέλεσμα"</string>
|
||||
<string name="revanced_hide_keyword_content_about_whole_words_title">Ταίριασμα ολόκληρων λέξεων</string>
|
||||
<!-- Translations _must_ use a localized example. For languages that do not use spaces between words (Chinese, Japanese, etc.) the English AI example should be used since no localized examples exist. Or if using machine translations, or if nobody wants to think of a localized example, then the English 'ai' example should be left as-is. -->
|
||||
@@ -421,7 +421,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_shopping_links_title">Σύνδεσμοι αγορών στην περιγραφή βίντεο</string>
|
||||
<string name="revanced_hide_shopping_links_summary_on">Κρυμμένοι</string>
|
||||
<string name="revanced_hide_shopping_links_summary_off">Εμφανίζονται</string>
|
||||
<!-- 'View products' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_view_products_banner_title">Ετικέτα «Προβολή προϊόντων» στην οθόνη αναπαραγωγής</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_on">Κρυμμένη</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_off">Εμφανίζεται</string>
|
||||
@@ -455,24 +454,31 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_summary_off">Εμφανίζεται</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">Αυτό δεν παρακάμπτει τον ηλικιακό περιορισμό. Απλώς τον αποδέχεται αυτόματα.</string>
|
||||
</patch>
|
||||
<patch id="interaction.doubletap.disableChapterSkipDoubleTapPatch">
|
||||
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
|
||||
<string name="revanced_disable_chapter_skip_double_tap_title">Απενεργοποίηση παράλειψης κεφαλαίου με διπλό πάτημα</string>
|
||||
<string name="revanced_disable_chapter_skip_double_tap_summary_on">Το διπλό πάτημα δεν παράλειπει στο επόμενο/προηγούμενο κεφάλαιο</string>
|
||||
<string name="revanced_disable_chapter_skip_double_tap_summary_off">Το διπλό πάτημα μπορεί περιστασιακά να παραλείψει στο επόμενο/προηγούμενο κεφάλαιο</string>
|
||||
</patch>
|
||||
<patch id="interaction.downloads.downloadsResourcePatch">
|
||||
<string name="revanced_external_downloader_screen_title">Εξωτερικές λήψεις</string>
|
||||
<string name="revanced_external_downloader_screen_summary">Ρυθμίσεις για χρήση εξωτερικού προγράμματος λήψης</string>
|
||||
<string name="revanced_external_downloader_screen_summary">Ρυθμίσεις για χρήση εξωτερικής εφαρμογής λήψης</string>
|
||||
<string name="revanced_external_downloader_title">Εμφάνιση κουμπιού εξωτερικής λήψης</string>
|
||||
<string name="revanced_external_downloader_summary_on">Το κουμπί λήψης εμφανίζεται στην οθόνη αναπαραγωγής</string>
|
||||
<string name="revanced_external_downloader_summary_off">Το κουμπί λήψης δεν εμφανίζεται στην οθόνη αναπαραγωγής</string>
|
||||
<string name="revanced_external_downloader_summary_on">Το κουμπί λήψης εμφανίζεται στην οθόνη αναπαραγωγής</string>
|
||||
<string name="revanced_external_downloader_summary_off">Το κουμπί λήψης δεν εμφανίζεται στην οθόνη αναπαραγωγής</string>
|
||||
<!-- 'Download action button' should be translated using the same wording as the translation of 'revanced_hide_download_button_title'. -->
|
||||
<string name="revanced_external_downloader_action_button_title">Μετατροπή κουμπιού ενέργειας «Λήψη»</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_on">Το κουμπί «Λήψη» θα ανοίγει το εξωτερικό πρόγραμμα λήψης σας</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_off">Το κουμπί «Λήψη» θα ανοίγει το ενσωματωμένο πρόγραμμα λήψης του YouTube</string>
|
||||
<string name="revanced_external_downloader_name_title">Όνομα πακέτου προγράμματος λήψης</string>
|
||||
<string name="revanced_external_downloader_name_summary">Το όνομα πακέτου της εγκατεστημένης σας εξωτερικής εφαρμογής λήψης όπως το NewPipe ή το Seal</string>
|
||||
<string name="revanced_external_downloader_action_button_title">Αλλαγή λειτουργίας κουμπιού ενέργειας «Λήψη»</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_on">Το κουμπί «Λήψη» ανοίγει την εξωτερική εφαρμογή λήψης σας</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_off">Το κουμπί «Λήψη» ανοίγει το ενσωματωμένο πρόγραμμα λήψης του YouTube</string>
|
||||
<string name="revanced_external_downloader_name_title">Όνομα πακέτου εφαρμογής λήψης</string>
|
||||
<string name="revanced_external_downloader_name_summary">Το όνομα πακέτου της εγκατεστημένης σας εξωτερικής εφαρμογής λήψης</string>
|
||||
<string name="revanced_external_downloader_other_item_hint">Εισάγετε το όνομα πακέτου</string>
|
||||
<string name="revanced_external_downloader_other_item">Άλλο</string>
|
||||
<string name="revanced_external_downloader_not_found_title">Η εφαρμογή δεν έχει εγκατασταθεί</string>
|
||||
<string name="revanced_external_downloader_not_installed_warning">Το %s δεν είναι εγκατεστημένο. Παρακαλούμε εγκαταστήστε το.</string>
|
||||
<string name="revanced_external_downloader_package_not_found_warning">"Δεν ήταν δυνατή η εύρεση εγκατεστημένης εφαρμογής με όνομα πακέτου: %s
|
||||
|
||||
Επιβεβαιώστε ότι το όνομα πακέτου είναι σωστό και ότι η εφαρμογή είναι εγκατεστημένη"</string>
|
||||
<string name="revanced_external_downloader_empty_warning">Το όνομα πακέτου δεν μπορεί να είναι κενό</string>
|
||||
</patch>
|
||||
<patch id="interaction.seekbar.disablePreciseSeekingGesturePatch">
|
||||
<string name="revanced_disable_precise_seeking_gesture_title">Απενεργοποίηση ακριβής αναζήτησης</string>
|
||||
@@ -735,7 +741,8 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_seekbar_title">Γραμμή προόδου στην οθόνη αναπαραγωγής</string>
|
||||
<string name="revanced_hide_seekbar_summary_on">Κρυμμένη</string>
|
||||
<string name="revanced_hide_seekbar_summary_off">Εμφανίζεται</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_title">Γραμμή προόδου σε μικρογραφίες βίντεο</string>
|
||||
<!-- Seekbar shown inside video thumbnails found the home/feed/search/history. The seekbar shows the prior watch progress when the video was last open. -->
|
||||
<string name="revanced_hide_seekbar_thumbnail_title">Γραμμή προόδου στις μικρογραφίες βίντεο</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_on">Κρυμμένη</string>
|
||||
<string name="revanced_hide_seekbar_thumbnail_summary_off">Εμφανίζεται</string>
|
||||
</patch>
|
||||
@@ -743,16 +750,16 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_shorts_player_screen_title">Οθόνη αναπαραγωγής Shorts</string>
|
||||
<string name="revanced_shorts_player_screen_summary">Απόκρυψη ή εμφάνιση στοιχείων στην οθόνη αναπαραγωγής Shorts</string>
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
|
||||
<string name="revanced_hide_shorts_home_title">Shorts στην αρχική σελίδα και στα σχετικά βίντεο</string>
|
||||
<string name="revanced_hide_shorts_home_title">Shorts στην αρχική ροή και στα σχετικά βίντεο</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">Κρυμμένα</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">Εμφανίζονται</string>
|
||||
<string name="revanced_hide_shorts_search_title">Shorts στα αποτελέσματα αναζήτησης</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">Κρυμμένα</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">Εμφανίζονται</string>
|
||||
<!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. -->
|
||||
<string name="revanced_hide_shorts_subscriptions_title">Shorts στην καρτέλα «Εγγραφές»</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">Κρυμμένα</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">Εμφανίζονται</string>
|
||||
<string name="revanced_hide_shorts_search_title">Shorts στα αποτελέσματα αναζήτησης</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">Κρυμμένα</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">Εμφανίζονται</string>
|
||||
<string name="revanced_hide_shorts_history_title">Shorts στο ιστορικό παρακολούθησης</string>
|
||||
<string name="revanced_hide_shorts_history_summary_on">Κρυμμένα</string>
|
||||
<string name="revanced_hide_shorts_history_summary_off">Εμφανίζονται</string>
|
||||
@@ -808,7 +815,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_shorts_use_sound_button_title">Κουμπί «Χρήση αυτού του ήχου»</string>
|
||||
<string name="revanced_hide_shorts_use_sound_button_summary_on">Κρυμμένο</string>
|
||||
<string name="revanced_hide_shorts_use_sound_button_summary_off">Εμφανίζεται</string>
|
||||
<string name="revanced_hide_shorts_use_template_button_title">Κουμπί «Χρήση προτύπου»</string>
|
||||
<string name="revanced_hide_shorts_use_template_button_title">Κουμπί «Χρήση αυτού του προτύπου»</string>
|
||||
<string name="revanced_hide_shorts_use_template_button_summary_on">Κρυμμένο</string>
|
||||
<string name="revanced_hide_shorts_use_template_button_summary_off">Εμφανίζεται</string>
|
||||
<string name="revanced_hide_shorts_like_fountain_title">Εφέ κουμπιού «Μου αρέσει»</string>
|
||||
@@ -862,9 +869,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_end_screen_suggested_video_summary_off">Εμφανίζεται</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.relatedvideooverlay.hideRelatedVideoOverlayPatch">
|
||||
<string name="revanced_hide_related_videos_overlay_title">Προεπισκόπηση σχετικών βίντεο στην πλήρη οθόνη</string>
|
||||
<string name="revanced_hide_related_videos_overlay_summary_on">Κρυμμένη</string>
|
||||
<string name="revanced_hide_related_videos_overlay_summary_off">Εμφανίζεται</string>
|
||||
<string name="revanced_hide_related_videos_overlay_title">Σχετικά βίντεο στην πλήρη οθόνη</string>
|
||||
<string name="revanced_hide_related_videos_overlay_summary_on">Κρυμμένα\n\nΑφορά τα σχετικά βίντεο της τελικής οθόνης στη λειτουργία πλήρους οθόνης</string>
|
||||
<string name="revanced_hide_related_videos_overlay_summary_off">Εμφανίζονται\n\nΑφορά τα σχετικά βίντεο της τελικής οθόνης στη λειτουργία πλήρους οθόνης</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.time.hideTimestampPatch">
|
||||
<string name="revanced_hide_timestamp_title">Χρονική πρόοδος βίντεο</string>
|
||||
@@ -885,8 +892,8 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.player.fullscreen.openVideosFullscreen">
|
||||
<string name="revanced_open_videos_fullscreen_portrait_title">Άνοιγμα των βίντεο σε πλήρη οθόνη με κατακόρυφη προβολή</string>
|
||||
<string name="revanced_open_videos_fullscreen_portrait_summary_on">Τα βίντεο ανοίγουν σε λειτουργία πλήρους οθόνης</string>
|
||||
<string name="revanced_open_videos_fullscreen_portrait_summary_off">Τα βίντεο δεν ανοίγουν σε λειτουργία πλήρους οθόνης</string>
|
||||
<string name="revanced_open_videos_fullscreen_portrait_summary_on">Τα βίντεο ανοίγουν αυτόματα σε λειτουργία πλήρους οθόνης</string>
|
||||
<string name="revanced_open_videos_fullscreen_portrait_summary_off">Τα βίντεο δεν ανοίγουν αυτόματα σε λειτουργία πλήρους οθόνης</string>
|
||||
</patch>
|
||||
<patch id="layout.player.overlay.customPlayerOverlayOpacityResourcePatch">
|
||||
<string name="revanced_player_overlay_opacity_title">Αδιαφάνεια φόντου οθόνης αναπαραγωγής</string>
|
||||
@@ -1119,7 +1126,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_sb_new_segment_disabled_category">Η κατηγορία είναι απενεργοποιημένη στις ρυθμίσεις. Ενεργοποιήστε την κατηγορία για υποβολή.</string>
|
||||
<string name="revanced_sb_new_segment_title">Νέο τμήμα SponsorBlock</string>
|
||||
<string name="revanced_sb_new_segment_mark_time_as_question">Ορισμός %s ως αρχή ή τέλος ενός νέου τμήματος;</string>
|
||||
<string name="revanced_sb_new_segment_mark_start">Έναρξη</string>
|
||||
<string name="revanced_sb_new_segment_mark_start">Αρχή</string>
|
||||
<string name="revanced_sb_new_segment_mark_end">Τέλος</string>
|
||||
<string name="revanced_sb_new_segment_now">Τώρα</string>
|
||||
<string name="revanced_sb_new_segment_time_start">Χρόνος έναρξης του τμήματος</string>
|
||||
@@ -1183,17 +1190,15 @@ Second \"item\" text"</string>
|
||||
• Η ροή οργανώνεται ανά θέματα και κανάλια"</string>
|
||||
</patch>
|
||||
<patch id="layout.spoofappversion.spoofAppVersionPatch">
|
||||
<string name="revanced_spoof_app_version_title">Τροποποίηση έκδοσης εφαρμογής</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_title">Παραποίηση έκδοσης εφαρμογής</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_user_dialog_message">"Η έκδοση της εφαρμογής YouTube θα παραποιηθεί σε παλιότερη.
|
||||
|
||||
Αυτό θα αλλάξει την εμφάνιση και τα χαρακτηριστικά της εφαρμογής, αλλά ενδέχεται να εμφανιστούν άγνωστες παρενέργειες.
|
||||
|
||||
Αν αργότερα απενεργοποιηθεί, συνιστάται η εκκαθάριση δεδομένων της εφαρμογής για την αποφυγή σφαλμάτων UI."</string>
|
||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_spoof_app_version_title'.
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch. -->
|
||||
<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 - Επαναφορά των παλιών εικονιδίων της οθόνης αναπαραγωγής Shorts</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_2">19.01.34 - Επαναφορά παλιών εικονιδίων γραμμής πλοήγησης</string>
|
||||
</patch>
|
||||
@@ -1328,7 +1333,7 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.alternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
|
||||
<string name="revanced_alt_thumbnail_home_title">Αρχική σελίδα</string>
|
||||
<string name="revanced_alt_thumbnail_home_title">Καρτέλα «Αρχική»</string>
|
||||
<!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. -->
|
||||
<string name="revanced_alt_thumbnail_subscription_title">Καρτέλα «Εγγραφές»</string>
|
||||
<!-- 'You' should be translated using the same localized wording YouTube displays for the You (Library) tab. -->
|
||||
@@ -1459,10 +1464,18 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_playback_speed_dialog_button_summary_on">Το κουμπί εμφανίζεται. Πατήστε παρατεταμένα για επαναφορά της ταχύτητας αναπαραγωγής στην προεπιλογή</string>
|
||||
<string name="revanced_playback_speed_dialog_button_summary_off">Το κουμπί δεν εμφανίζεται</string>
|
||||
</patch>
|
||||
<patch id="video.quality.button.videoQualityButtonPatch">
|
||||
<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_off">Το κουμπί δεν εμφανίζεται</string>
|
||||
</patch>
|
||||
<patch id="video.speed.custom.customPlaybackSpeedPatch">
|
||||
<string name="revanced_custom_speed_menu_title">Μενού προσαρμοσμένης ταχύτητας αναπαραγωγής</string>
|
||||
<string name="revanced_custom_speed_menu_summary_on">Το μενού προσαρμοσμένης ταχύτητας αναπαραγωγής εμφανίζεται</string>
|
||||
<string name="revanced_custom_speed_menu_summary_off">Το μενού προσαρμοσμένης ταχύτητας αναπαραγωγής δεν εμφανίζεται</string>
|
||||
<string name="revanced_restore_old_speed_menu_title">Επαναφορά παλιού μενού ταχύτητας αναπαραγωγής</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_on">Το παλιό μενού ταχύτητας εμφανίζεται</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_off">Το σύγχρονο μενού ταχύτητας εμφανίζεται</string>
|
||||
<string name="revanced_custom_playback_speeds_title">Προσαρμοσμένες ταχύτητες αναπαραγωγής</string>
|
||||
<string name="revanced_custom_playback_speeds_summary">Προσθέστε ή αλλάξτε τις προσαρμοσμένες ταχύτητες αναπαραγωγής</string>
|
||||
<string name="revanced_custom_playback_speeds_invalid">Οι ταχύτητες πρέπει να είναι μικρότερες από %sx</string>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user