mirror of
https://github.com/ReVanced/revanced-patches.git
synced 2026-01-15 15:33:13 +00:00
Compare commits
34 Commits
v5.28.0-de
...
v5.29.0-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
113a3d9f19 | ||
|
|
978c24458b | ||
|
|
957bece3e9 | ||
|
|
d32c3ac51d | ||
|
|
26102a70a2 | ||
|
|
2b44bf4c23 | ||
|
|
0e63f49e13 | ||
|
|
674a5b8d29 | ||
|
|
7be374100b | ||
|
|
e48c152b95 | ||
|
|
a678f178e1 | ||
|
|
2d8f5641f9 | ||
|
|
0dbd058099 | ||
|
|
c1a8fd0766 | ||
|
|
d338989cb4 | ||
|
|
b94daacf01 | ||
|
|
c764c4f197 | ||
|
|
6b719dfcd7 | ||
|
|
ccd169121a | ||
|
|
dcfbd8bf93 | ||
|
|
b65697603d | ||
|
|
25da5cca8b | ||
|
|
2b62fc2224 | ||
|
|
a9e9456b6b | ||
|
|
b01523e97d | ||
|
|
b8afb4e821 | ||
|
|
0d2198faed | ||
|
|
5c7c407b82 | ||
|
|
a8d2a1e028 | ||
|
|
d31624cae8 | ||
|
|
e790cfbf59 | ||
|
|
a54d408d3e | ||
|
|
5d3769e921 | ||
|
|
e138501657 |
108
CHANGELOG.md
108
CHANGELOG.md
@@ -1,3 +1,111 @@
|
||||
# [5.29.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.29.0-dev.6...v5.29.0-dev.7) (2025-06-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide layout components:** Fix "Hide video description attributes" ([#5250](https://github.com/ReVanced/revanced-patches/issues/5250)) ([2f22d45](https://github.com/ReVanced/revanced-patches/commit/2f22d45eb80745ac64fbea44c8055ebe7925a586))
|
||||
* **YouTube - Hide Shorts components:** Fix "Hide Use this template button" ([#5249](https://github.com/ReVanced/revanced-patches/issues/5249)) ([b399ecb](https://github.com/ReVanced/revanced-patches/commit/b399ecbb6a222d82dd5e4b3417c9f7eff4324adb))
|
||||
|
||||
# [5.29.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.29.0-dev.5...v5.29.0-dev.6) (2025-06-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide video action buttons:** Add `Hide Stop ads` ([#5245](https://github.com/ReVanced/revanced-patches/issues/5245)) ([274dcc6](https://github.com/ReVanced/revanced-patches/commit/274dcc676e009be63eb6970de33abacd34dc6560))
|
||||
|
||||
# [5.29.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.29.0-dev.4...v5.29.0-dev.5) (2025-06-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Google Photos:** Resolve startup crash for Android 5.0 devices ([0294533](https://github.com/ReVanced/revanced-patches/commit/0294533c4d9a321aea086eedb4e46385ae9a026e))
|
||||
|
||||
# [5.29.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.29.0-dev.3...v5.29.0-dev.4) (2025-06-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide Shorts components:** Fix "Hide Use this sound button" ([#5233](https://github.com/ReVanced/revanced-patches/issues/5233)) ([5d6ec9e](https://github.com/ReVanced/revanced-patches/commit/5d6ec9e94a6221a0f32762d5bede893e9e7457fc))
|
||||
|
||||
# [5.29.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.29.0-dev.2...v5.29.0-dev.3) (2025-06-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Fix refactoring app startup exception ([1b00c90](https://github.com/ReVanced/revanced-patches/commit/1b00c907f4b90f4659afb4a54ba61ac2835b460d))
|
||||
|
||||
# [5.29.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.29.0-dev.1...v5.29.0-dev.2) (2025-06-23)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Crunchyroll:** Add `Hide ads` patch ([#5201](https://github.com/ReVanced/revanced-patches/issues/5201)) ([46b4398](https://github.com/ReVanced/revanced-patches/commit/46b4398fd6ca223391ed8f497a8347c2313421b7))
|
||||
|
||||
# [5.29.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.28.1-dev.2...v5.29.0-dev.1) (2025-06-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Always use single threaded layout to resolve layout bugs in unpatched YouTube ([#5226](https://github.com/ReVanced/revanced-patches/issues/5226)) ([1f539b1](https://github.com/ReVanced/revanced-patches/commit/1f539b1396526b2c767d77a804bd0308ee4a42ec))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Add an option to disable toasts when changing default playback speed or quality ([#5230](https://github.com/ReVanced/revanced-patches/issues/5230)) ([c68cde3](https://github.com/ReVanced/revanced-patches/commit/c68cde3a896450874cc571be5c4723387db96032))
|
||||
|
||||
## [5.28.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.28.1-dev.1...v5.28.1-dev.2) (2025-06-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide ads:** Hide new type of product ad in video description ([#5225](https://github.com/ReVanced/revanced-patches/issues/5225)) ([1e2efad](https://github.com/ReVanced/revanced-patches/commit/1e2efad7b2714c395ed6b0a77cbbf8a2265df520))
|
||||
|
||||
## [5.28.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.28.0...v5.28.1-dev.1) (2025-06-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Add scrollable content to modern style settings dialogs ([#5211](https://github.com/ReVanced/revanced-patches/issues/5211)) ([e6876d5](https://github.com/ReVanced/revanced-patches/commit/e6876d510d28f6a3a41ec1722a033b3e30a22c65))
|
||||
|
||||
# [5.28.0](https://github.com/ReVanced/revanced-patches/compare/v5.27.0...v5.28.0) (2025-06-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Google Photos:** Resolve startup crash if MicroG GmsCore does not already have granted permissions ([a93d74d](https://github.com/ReVanced/revanced-patches/commit/a93d74d26e7ef87a3745df2b9fe82722d65a0e59))
|
||||
* **Messenger - Remove Meta AI:** Improve patch logic ([#5153](https://github.com/ReVanced/revanced-patches/issues/5153)) ([4ad4887](https://github.com/ReVanced/revanced-patches/commit/4ad488744d87543c31e453dc7b6d8182b3a7f440))
|
||||
* **Pandora - Disable ads:** Support latest app target ([#5185](https://github.com/ReVanced/revanced-patches/issues/5185)) ([ca83047](https://github.com/ReVanced/revanced-patches/commit/ca83047f5c4acbb267d5b98db80ad111999086e0))
|
||||
* **Spotify:** Fix `Hide Create button` and `Sanitize sharing links` for older but supported app targets ([#5159](https://github.com/ReVanced/revanced-patches/issues/5159)) ([e7dd061](https://github.com/ReVanced/revanced-patches/commit/e7dd061c513af90861c0ab0d7adc6ee43be57ce2))
|
||||
* **Threads - Hide ads:** Constrain patch to the last working app target ([#5189](https://github.com/ReVanced/revanced-patches/issues/5189)) ([3558c44](https://github.com/ReVanced/revanced-patches/commit/3558c44a05c13f19fefdbbf14b364181a79f17c0))
|
||||
* **YouTube:** Remove old app targets that are no longer supported by YouTube ([#5192](https://github.com/ReVanced/revanced-patches/issues/5192)) ([c9e54e1](https://github.com/ReVanced/revanced-patches/commit/c9e54e1d36243945ac1ec3108fe38edf0e15d772))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Spotify:** Add `Change lyrics provider` patch ([#4937](https://github.com/ReVanced/revanced-patches/issues/4937)) ([8736b6a](https://github.com/ReVanced/revanced-patches/commit/8736b6a80b48cb1f4562c9f9919804006ddb18bd))
|
||||
* Use modern style settings dialogs ([#5109](https://github.com/ReVanced/revanced-patches/issues/5109)) ([312b6dc](https://github.com/ReVanced/revanced-patches/commit/312b6dc04e01c2758cd304ca8606306027aa2f01))
|
||||
|
||||
# [5.28.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.28.0-dev.7...v5.28.0-dev.8) (2025-06-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Messenger - Remove Meta AI:** Improve patch logic ([#5153](https://github.com/ReVanced/revanced-patches/issues/5153)) ([4ad4887](https://github.com/ReVanced/revanced-patches/commit/4ad488744d87543c31e453dc7b6d8182b3a7f440))
|
||||
|
||||
# [5.28.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.28.0-dev.6...v5.28.0-dev.7) (2025-06-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Remove old app targets that are no longer supported by YouTube ([#5192](https://github.com/ReVanced/revanced-patches/issues/5192)) ([c9e54e1](https://github.com/ReVanced/revanced-patches/commit/c9e54e1d36243945ac1ec3108fe38edf0e15d772))
|
||||
|
||||
# [5.28.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.28.0-dev.5...v5.28.0-dev.6) (2025-06-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Threads - Hide ads:** Constrain patch to the last working app target ([#5189](https://github.com/ReVanced/revanced-patches/issues/5189)) ([3558c44](https://github.com/ReVanced/revanced-patches/commit/3558c44a05c13f19fefdbbf14b364181a79f17c0))
|
||||
|
||||
# [5.28.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.28.0-dev.4...v5.28.0-dev.5) (2025-06-17)
|
||||
|
||||
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
package app.revanced.extension.messenger.metaai;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class RemoveMetaAIPatch {
|
||||
private static final Set<Long> loggedIDs = Collections.synchronizedSet(new HashSet<>());
|
||||
|
||||
public static boolean overrideBooleanFlag(long id, boolean value) {
|
||||
// This catches all flag IDs related to Meta AI.
|
||||
// The IDs change slightly with every update,
|
||||
// so to work around this, IDs from different versions were compared
|
||||
// to find what they have in common, which turned out to be those first bits.
|
||||
// TODO: Find the specific flags that we care about and patch the code they control instead.
|
||||
if ((id & 0x7FFFFFC000000000L) == 0x810A8000000000L) {
|
||||
return false;
|
||||
try {
|
||||
if (Long.toString(id).startsWith("REPLACED_BY_PATCH")) {
|
||||
if (loggedIDs.add(id))
|
||||
Logger.printInfo(() -> "Overriding " + id + " from " + value + " to false");
|
||||
|
||||
return false;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "overrideBooleanFlag failure", ex);
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
@@ -19,7 +19,6 @@ import android.util.Pair;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
@@ -28,7 +27,6 @@ import java.util.Locale;
|
||||
|
||||
import app.revanced.extension.shared.requests.Requester;
|
||||
import app.revanced.extension.shared.requests.Route;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class GmsCoreSupport {
|
||||
@@ -109,7 +107,6 @@ public class GmsCoreSupport {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
public static void checkGmsCore(Activity context) {
|
||||
try {
|
||||
// Verify the user has not included GmsCore for a root installation.
|
||||
@@ -157,7 +154,9 @@ public class GmsCoreSupport {
|
||||
}
|
||||
|
||||
// Check if GmsCore is currently running in the background.
|
||||
try (var client = context.getContentResolver().acquireContentProviderClient(GMS_CORE_PROVIDER)) {
|
||||
var client = context.getContentResolver().acquireContentProviderClient(GMS_CORE_PROVIDER);
|
||||
//noinspection TryFinallyCanBeTryWithResources
|
||||
try {
|
||||
if (client == null) {
|
||||
Logger.printInfo(() -> "GmsCore is not running in the background");
|
||||
checkIfDontKillMyAppSupportsManufacturer();
|
||||
@@ -167,6 +166,8 @@ public class GmsCoreSupport {
|
||||
"gms_core_dialog_open_website_text",
|
||||
(dialog, id) -> openDontKillMyApp());
|
||||
}
|
||||
} finally {
|
||||
if (client != null) client.close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "checkGmsCore failure", ex);
|
||||
@@ -226,6 +227,11 @@ public class GmsCoreSupport {
|
||||
* @return If GmsCore is not whitelisted from battery optimizations.
|
||||
*/
|
||||
private static boolean batteryOptimizationsEnabled(Context context) {
|
||||
//noinspection ObsoleteSdkInt
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
// Android 5.0 does not have battery optimization settings.
|
||||
return false;
|
||||
}
|
||||
var powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
return !powerManager.isIgnoringBatteryOptimizations(GMS_CORE_PACKAGE_NAME);
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.Toolbar;
|
||||
@@ -773,16 +774,15 @@ public class Utils {
|
||||
Dialog dialog = new Dialog(context);
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); // Remove default title bar.
|
||||
|
||||
// Create main layout.
|
||||
LinearLayout mainLayout = new LinearLayout(context);
|
||||
mainLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
// Preset size constants.
|
||||
final int dip4 = dipToPixels(4);
|
||||
final int dip8 = dipToPixels(8);
|
||||
final int dip16 = dipToPixels(16);
|
||||
final int dip24 = dipToPixels(24);
|
||||
|
||||
// Create main layout.
|
||||
LinearLayout mainLayout = new LinearLayout(context);
|
||||
mainLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
mainLayout.setPadding(dip24, dip16, dip24, dip24);
|
||||
// Set rounded rectangle background.
|
||||
ShapeDrawable mainBackground = new ShapeDrawable(new RoundRectShape(
|
||||
@@ -802,55 +802,71 @@ public class Utils {
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
);
|
||||
layoutParams.setMargins(0, 0, 0, dip8);
|
||||
layoutParams.setMargins(0, 0, 0, dip16);
|
||||
titleView.setLayoutParams(layoutParams);
|
||||
mainLayout.addView(titleView);
|
||||
}
|
||||
|
||||
// Message (if not replaced by EditText).
|
||||
if (editText == null && message != null) {
|
||||
TextView messageView = new TextView(context);
|
||||
messageView.setText(message); // Supports Spanned (HTML).
|
||||
messageView.setTextSize(16);
|
||||
messageView.setTextColor(getAppForegroundColor());
|
||||
// Enable HTML link clicking if the message contains links.
|
||||
if (message instanceof Spanned) {
|
||||
messageView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
// Create content container (message/EditText) inside a ScrollView only if message or editText is provided.
|
||||
ScrollView contentScrollView = null;
|
||||
LinearLayout contentContainer = null;
|
||||
if (message != null || editText != null) {
|
||||
contentScrollView = new ScrollView(context);
|
||||
contentScrollView.setVerticalScrollBarEnabled(false); // Disable the vertical scrollbar.
|
||||
contentScrollView.setOverScrollMode(View.OVER_SCROLL_NEVER);
|
||||
if (editText != null) {
|
||||
ShapeDrawable scrollViewBackground = new ShapeDrawable(new RoundRectShape(
|
||||
createCornerRadii(10), null, null));
|
||||
scrollViewBackground.getPaint().setColor(getEditTextBackground());
|
||||
contentScrollView.setPadding(dip8, dip8, dip8, dip8);
|
||||
contentScrollView.setBackground(scrollViewBackground);
|
||||
contentScrollView.setClipToOutline(true);
|
||||
}
|
||||
LinearLayout.LayoutParams messageParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams contentParams = new LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
0,
|
||||
1.0f // Weight to take available space.
|
||||
);
|
||||
messageParams.setMargins(0, dip8, 0, dip16);
|
||||
messageView.setLayoutParams(messageParams);
|
||||
mainLayout.addView(messageView);
|
||||
}
|
||||
contentScrollView.setLayoutParams(contentParams);
|
||||
contentContainer = new LinearLayout(context);
|
||||
contentContainer.setOrientation(LinearLayout.VERTICAL);
|
||||
contentScrollView.addView(contentContainer);
|
||||
|
||||
// EditText (if provided).
|
||||
if (editText != null) {
|
||||
// Remove EditText from its current parent, if any.
|
||||
ViewGroup parent = (ViewGroup) editText.getParent();
|
||||
if (parent != null) {
|
||||
parent.removeView(editText);
|
||||
// Message (if not replaced by EditText).
|
||||
if (editText == null && message != null) {
|
||||
TextView messageView = new TextView(context);
|
||||
messageView.setText(message); // Supports Spanned (HTML).
|
||||
messageView.setTextSize(16);
|
||||
messageView.setTextColor(getAppForegroundColor());
|
||||
// Enable HTML link clicking if the message contains links.
|
||||
if (message instanceof Spanned) {
|
||||
messageView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
LinearLayout.LayoutParams messageParams = new LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
);
|
||||
messageView.setLayoutParams(messageParams);
|
||||
contentContainer.addView(messageView);
|
||||
}
|
||||
// Style the EditText to match the dialog theme.
|
||||
editText.setTextColor(getAppForegroundColor());
|
||||
editText.setBackgroundColor(isDarkModeEnabled() ? Color.BLACK : Color.WHITE);
|
||||
editText.setPadding(dip8, dip8, dip8, dip8);
|
||||
ShapeDrawable editTextBackground = new ShapeDrawable(new RoundRectShape(
|
||||
createCornerRadii(10), null, null));
|
||||
editTextBackground.getPaint().setColor(getEditTextBackground()); // Background color for EditText.
|
||||
editText.setBackground(editTextBackground);
|
||||
|
||||
LinearLayout.LayoutParams editTextParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
);
|
||||
editTextParams.setMargins(0, dip8, 0, dip16);
|
||||
// Prevent buttons from moving off the screen by fixing the height of the EditText.
|
||||
final int maxHeight = (int) (context.getResources().getDisplayMetrics().heightPixels * 0.6);
|
||||
editText.setMaxHeight(maxHeight);
|
||||
mainLayout.addView(editText, 1, editTextParams);
|
||||
// EditText (if provided).
|
||||
if (editText != null) {
|
||||
// Remove EditText from its current parent, if any.
|
||||
ViewGroup parent = (ViewGroup) editText.getParent();
|
||||
if (parent != null) {
|
||||
parent.removeView(editText);
|
||||
}
|
||||
// Style the EditText to match the dialog theme.
|
||||
editText.setTextColor(getAppForegroundColor());
|
||||
editText.setBackgroundColor(Color.TRANSPARENT);
|
||||
editText.setPadding(0, 0, 0, 0);
|
||||
LinearLayout.LayoutParams editTextParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
);
|
||||
contentContainer.addView(editText, editTextParams);
|
||||
}
|
||||
}
|
||||
|
||||
// Button container.
|
||||
@@ -861,7 +877,7 @@ public class Utils {
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
);
|
||||
buttonContainerParams.setMargins(0, dip8, 0, 0);
|
||||
buttonContainerParams.setMargins(0, dip16, 0, 0);
|
||||
buttonContainer.setLayoutParams(buttonContainerParams);
|
||||
|
||||
// Lists to track buttons.
|
||||
@@ -1036,25 +1052,29 @@ public class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
// Add ScrollView to main layout only if content exist.
|
||||
if (contentScrollView != null) {
|
||||
mainLayout.addView(contentScrollView);
|
||||
}
|
||||
mainLayout.addView(buttonContainer);
|
||||
dialog.setContentView(mainLayout);
|
||||
|
||||
// Set dialog window attributes.
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
setDialogWindowParameters(context, window);
|
||||
setDialogWindowParameters(window);
|
||||
}
|
||||
|
||||
return new Pair<>(dialog, mainLayout);
|
||||
}
|
||||
|
||||
public static void setDialogWindowParameters(Context context, Window window) {
|
||||
public static void setDialogWindowParameters(Window window) {
|
||||
WindowManager.LayoutParams params = window.getAttributes();
|
||||
|
||||
Resources resources = context.getResources();
|
||||
DisplayMetrics displayMetrics = resources.getDisplayMetrics();
|
||||
DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
|
||||
int portraitWidth = (int) (displayMetrics.widthPixels * 0.9);
|
||||
if (resources.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
|
||||
if (Resources.getSystem().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
portraitWidth = (int) Math.min(portraitWidth, displayMetrics.heightPixels * 0.9);
|
||||
}
|
||||
params.width = portraitWidth;
|
||||
@@ -1199,7 +1219,7 @@ public class Utils {
|
||||
return darkColor == Color.BLACK
|
||||
// Lighten the background a little if using AMOLED dark theme
|
||||
// as the dialogs are almost invisible.
|
||||
? 0xFF0D0D0D
|
||||
? 0xFF080808 // 3%
|
||||
: darkColor;
|
||||
}
|
||||
return getThemeLightColor();
|
||||
|
||||
@@ -129,8 +129,7 @@ abstract class Check {
|
||||
ImageView iconView = new ImageView(activity);
|
||||
iconView.setImageResource(Utils.getResourceIdentifier("revanced_ic_dialog_alert", "drawable"));
|
||||
iconView.setColorFilter(Utils.getAppForegroundColor(), PorterDuff.Mode.SRC_IN);
|
||||
final int dip8 = dipToPixels(8);
|
||||
iconView.setPadding(0, dip8, 0, dip8);
|
||||
iconView.setPadding(0, 0, 0, 0);
|
||||
LinearLayout.LayoutParams iconParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
|
||||
@@ -24,10 +24,7 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.*;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
|
||||
@@ -298,7 +295,6 @@ public class ColorPickerPreference extends EditTextPreference {
|
||||
// Horizontal layout for preview and EditText.
|
||||
LinearLayout inputLayout = new LinearLayout(context);
|
||||
inputLayout.setOrientation(LinearLayout.HORIZONTAL);
|
||||
inputLayout.setPadding(0, 0, 0, dipToPixels(10));
|
||||
|
||||
dialogColorPreview = new TextView(context);
|
||||
LinearLayout.LayoutParams previewParams = new LinearLayout.LayoutParams(
|
||||
@@ -338,11 +334,23 @@ public class ColorPickerPreference extends EditTextPreference {
|
||||
paddingView.setLayoutParams(params);
|
||||
inputLayout.addView(paddingView);
|
||||
|
||||
// Create main container for color picker and input layout.
|
||||
LinearLayout container = new LinearLayout(context);
|
||||
container.setOrientation(LinearLayout.VERTICAL);
|
||||
container.addView(colorPicker);
|
||||
container.addView(inputLayout);
|
||||
// Create content container for color picker and input layout.
|
||||
LinearLayout contentContainer = new LinearLayout(context);
|
||||
contentContainer.setOrientation(LinearLayout.VERTICAL);
|
||||
contentContainer.addView(colorPicker);
|
||||
contentContainer.addView(inputLayout);
|
||||
|
||||
// Create ScrollView to wrap the content container.
|
||||
ScrollView contentScrollView = new ScrollView(context);
|
||||
contentScrollView.setVerticalScrollBarEnabled(false); // Disable vertical scrollbar.
|
||||
contentScrollView.setOverScrollMode(View.OVER_SCROLL_NEVER); // Disable overscroll effect.
|
||||
LinearLayout.LayoutParams scrollViewParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
0,
|
||||
1.0f
|
||||
);
|
||||
contentScrollView.setLayoutParams(scrollViewParams);
|
||||
contentScrollView.addView(contentContainer);
|
||||
|
||||
// Create custom dialog.
|
||||
final int originalColor = currentColor & 0x00FFFFFF;
|
||||
@@ -391,9 +399,9 @@ public class ColorPickerPreference extends EditTextPreference {
|
||||
false // Do not dismiss dialog when onNeutralClick.
|
||||
);
|
||||
|
||||
// Add the custom container to the dialog's main layout.
|
||||
// Add the ScrollView to the dialog's main layout.
|
||||
LinearLayout dialogMainLayout = dialogPair.second;
|
||||
dialogMainLayout.addView(container, 1);
|
||||
dialogMainLayout.addView(contentScrollView, dialogMainLayout.getChildCount() - 1);
|
||||
|
||||
// Set up color picker listener with debouncing.
|
||||
// Add listener last to prevent callbacks from set calls above.
|
||||
|
||||
@@ -11,11 +11,7 @@ import android.util.Pair;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.*;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
@@ -107,14 +103,16 @@ public class CustomDialogListPreference extends ListPreference {
|
||||
|
||||
@Override
|
||||
protected void showDialog(Bundle state) {
|
||||
Context context = getContext();
|
||||
|
||||
// Create ListView.
|
||||
ListView listView = new ListView(getContext());
|
||||
ListView listView = new ListView(context);
|
||||
listView.setId(android.R.id.list);
|
||||
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
|
||||
|
||||
// Create custom adapter for the ListView.
|
||||
ListPreferenceArrayAdapter adapter = new ListPreferenceArrayAdapter(
|
||||
getContext(),
|
||||
context,
|
||||
Utils.getResourceIdentifier("revanced_custom_list_item_checked", "layout"),
|
||||
getEntries(),
|
||||
getEntryValues(),
|
||||
@@ -137,7 +135,7 @@ public class CustomDialogListPreference extends ListPreference {
|
||||
|
||||
// Create the custom dialog without OK button.
|
||||
Pair<Dialog, LinearLayout> dialogPair = Utils.createCustomDialog(
|
||||
getContext(),
|
||||
context,
|
||||
getTitle() != null ? getTitle().toString() : "",
|
||||
null,
|
||||
null,
|
||||
@@ -149,35 +147,13 @@ public class CustomDialogListPreference extends ListPreference {
|
||||
true
|
||||
);
|
||||
|
||||
Dialog dialog = dialogPair.first;
|
||||
// Add the ListView to the main layout.
|
||||
LinearLayout mainLayout = dialogPair.second;
|
||||
|
||||
// Measure content height before adding ListView to layout.
|
||||
// Otherwise, the ListView will push the buttons off the screen.
|
||||
int totalHeight = 0;
|
||||
int widthSpec = View.MeasureSpec.makeMeasureSpec(
|
||||
getContext().getResources().getDisplayMetrics().widthPixels,
|
||||
View.MeasureSpec.AT_MOST
|
||||
);
|
||||
int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
|
||||
|
||||
for (int i = 0; i < adapter.getCount(); i++) {
|
||||
View listItem = adapter.getView(i, null, listView);
|
||||
listItem.measure(widthSpec, heightSpec);
|
||||
totalHeight += listItem.getMeasuredHeight();
|
||||
}
|
||||
|
||||
// Cap the height at maxHeight.
|
||||
int maxHeight = (int) (getContext().getResources().getDisplayMetrics().heightPixels * 0.6);
|
||||
int finalHeight = Math.min(totalHeight, maxHeight);
|
||||
|
||||
// Add ListView to the main layout with calculated height.
|
||||
LinearLayout.LayoutParams listViewParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
finalHeight // Use calculated height directly.
|
||||
0,
|
||||
1.0f
|
||||
);
|
||||
final int marginHorizontal = dipToPixels(8);
|
||||
listViewParams.setMargins(0, marginHorizontal, 0, marginHorizontal);
|
||||
mainLayout.addView(listView, mainLayout.getChildCount() - 1, listViewParams);
|
||||
|
||||
// Handle item click to select value and dismiss dialog.
|
||||
@@ -188,10 +164,10 @@ public class CustomDialogListPreference extends ListPreference {
|
||||
adapter.setSelectedValue(selectedValue);
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
dialog.dismiss();
|
||||
dialogPair.first.dismiss();
|
||||
});
|
||||
|
||||
// Show the dialog.
|
||||
dialog.show();
|
||||
dialogPair.first.show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.preference.Preference;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
@@ -216,6 +217,8 @@ class WebViewDialog extends Dialog {
|
||||
|
||||
// Create WebView.
|
||||
WebView webView = new WebView(getContext());
|
||||
webView.setVerticalScrollBarEnabled(false); // Disable the vertical scrollbar.
|
||||
webView.setOverScrollMode(View.OVER_SCROLL_NEVER);
|
||||
webView.getSettings().setJavaScriptEnabled(true);
|
||||
webView.setWebViewClient(new OpenLinksExternallyWebClient());
|
||||
webView.loadDataWithBaseURL(null, htmlContent, "text/html", "utf-8", null);
|
||||
@@ -228,7 +231,7 @@ class WebViewDialog extends Dialog {
|
||||
// Set dialog window attributes
|
||||
Window window = getWindow();
|
||||
if (window != null) {
|
||||
Utils.setDialogWindowParameters(getContext(), window);
|
||||
Utils.setDialogWindowParameters(window);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,11 +7,17 @@ public class VersionCheckPatch {
|
||||
return Utils.getAppVersionName().compareTo(version) >= 0;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static final boolean IS_19_17_OR_GREATER = isVersionOrGreater("19.17.00");
|
||||
@Deprecated
|
||||
public static final boolean IS_19_20_OR_GREATER = isVersionOrGreater("19.20.00");
|
||||
@Deprecated
|
||||
public static final boolean IS_19_21_OR_GREATER = isVersionOrGreater("19.21.00");
|
||||
@Deprecated
|
||||
public static final boolean IS_19_26_OR_GREATER = isVersionOrGreater("19.26.00");
|
||||
@Deprecated
|
||||
public static final boolean IS_19_29_OR_GREATER = isVersionOrGreater("19.29.00");
|
||||
@Deprecated
|
||||
public static final boolean IS_19_34_OR_GREATER = isVersionOrGreater("19.34.00");
|
||||
public static final boolean IS_19_46_OR_GREATER = isVersionOrGreater("19.46.00");
|
||||
}
|
||||
|
||||
@@ -121,12 +121,14 @@ public final class AdsFilter extends Filter {
|
||||
|
||||
playerShoppingShelf = new StringFilterGroup(
|
||||
Settings.HIDE_PLAYER_STORE_SHELF,
|
||||
"expandable_list.eml",
|
||||
"horizontal_shelf.eml"
|
||||
);
|
||||
|
||||
playerShoppingShelfBuffer = new ByteArrayFilterGroup(
|
||||
null,
|
||||
"shopping_item_card_list.eml"
|
||||
"shopping_link_item",
|
||||
"shopping_item_card_list"
|
||||
);
|
||||
|
||||
channelProfile = new StringFilterGroup(
|
||||
|
||||
@@ -46,7 +46,7 @@ final class ButtonsFilter extends Filter {
|
||||
"|download_button.eml"
|
||||
),
|
||||
new StringFilterGroup(
|
||||
Settings.HIDE_PLAYLIST_BUTTON,
|
||||
Settings.HIDE_SAVE_BUTTON,
|
||||
"|save_to_playlist_button"
|
||||
),
|
||||
new StringFilterGroup(
|
||||
@@ -76,6 +76,10 @@ final class ButtonsFilter extends Filter {
|
||||
Settings.HIDE_ASK_BUTTON,
|
||||
"yt_fill_spark"
|
||||
),
|
||||
new ByteArrayFilterGroup(
|
||||
Settings.HIDE_STOP_ADS_BUTTON,
|
||||
"yt_outline_slash_circle_left"
|
||||
),
|
||||
// Check for clip button both here and using a path filter,
|
||||
// as there's a chance the path is a generic action button and won't contain 'clip_button'
|
||||
new ByteArrayFilterGroup(
|
||||
|
||||
@@ -14,6 +14,9 @@ final class DescriptionComponentsFilter extends Filter {
|
||||
|
||||
private final StringFilterGroup macroMarkersCarousel;
|
||||
|
||||
private final StringFilterGroup horizontalShelf;
|
||||
private final ByteArrayFilterGroup cellVideoAttribute;
|
||||
|
||||
public DescriptionComponentsFilter() {
|
||||
exceptions.addPatterns(
|
||||
"compact_channel",
|
||||
@@ -35,8 +38,7 @@ final class DescriptionComponentsFilter extends Filter {
|
||||
|
||||
final StringFilterGroup attributesSection = new StringFilterGroup(
|
||||
Settings.HIDE_ATTRIBUTES_SECTION,
|
||||
"gaming_section",
|
||||
"music_section",
|
||||
// "gaming_section", "music_section"
|
||||
"video_attributes_section"
|
||||
);
|
||||
|
||||
@@ -76,15 +78,26 @@ final class DescriptionComponentsFilter extends Filter {
|
||||
)
|
||||
);
|
||||
|
||||
horizontalShelf = new StringFilterGroup(
|
||||
Settings.HIDE_ATTRIBUTES_SECTION,
|
||||
"horizontal_shelf.eml"
|
||||
);
|
||||
|
||||
cellVideoAttribute = new ByteArrayFilterGroup(
|
||||
null,
|
||||
"cell_video_attribute"
|
||||
);
|
||||
|
||||
addPathCallbacks(
|
||||
aiGeneratedVideoSummarySection,
|
||||
askSection,
|
||||
attributesSection,
|
||||
infoCardsSection,
|
||||
horizontalShelf,
|
||||
howThisWasMadeSection,
|
||||
macroMarkersCarousel,
|
||||
podcastSection,
|
||||
transcriptSection,
|
||||
macroMarkersCarousel
|
||||
transcriptSection
|
||||
);
|
||||
}
|
||||
|
||||
@@ -97,6 +110,10 @@ final class DescriptionComponentsFilter extends Filter {
|
||||
return contentIndex == 0 && macroMarkersCarouselGroupList.check(protobufBufferArray).isFiltered();
|
||||
}
|
||||
|
||||
if (matchedGroup == horizontalShelf) {
|
||||
return cellVideoAttribute.check(protobufBufferArray).isFiltered();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,27 @@ public final class LithoFilterPatch {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Litho layout fixed thread pool size override.
|
||||
* <p>
|
||||
* Unpatched YouTube uses a layout fixed thread pool between 1 and 3 threads:
|
||||
* <pre>
|
||||
* 1 thread - > Device has less than 6 cores
|
||||
* 2 threads -> Device has over 6 cores and less than 6GB of memory
|
||||
* 3 threads -> Device has over 6 cores and more than 6GB of memory
|
||||
* </pre>
|
||||
*
|
||||
* Using more than 1 thread causes layout issues such as the You tab watch/playlist shelf
|
||||
* that is sometimes incorrectly hidden (ReVanced is not hiding it), and seems to
|
||||
* fix a race issue if using the active navigation tab status with litho filtering.
|
||||
*/
|
||||
private static final int LITHO_LAYOUT_THREAD_POOL_SIZE = 1;
|
||||
|
||||
/**
|
||||
* Placeholder for actual filters.
|
||||
*/
|
||||
private static final class DummyFilter extends Filter { }
|
||||
|
||||
private static final Filter[] filters = new Filter[] {
|
||||
new DummyFilter() // Replaced by patch.
|
||||
};
|
||||
@@ -213,9 +234,28 @@ public final class LithoFilterPatch {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Placeholder for actual filters.
|
||||
*/
|
||||
final class DummyFilter extends Filter { }
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static int getExecutorCorePoolSize(int originalCorePoolSize) {
|
||||
if (originalCorePoolSize != LITHO_LAYOUT_THREAD_POOL_SIZE) {
|
||||
Logger.printDebug(() -> "Overriding core thread pool size from: " + originalCorePoolSize
|
||||
+ " to: " + LITHO_LAYOUT_THREAD_POOL_SIZE);
|
||||
}
|
||||
|
||||
return LITHO_LAYOUT_THREAD_POOL_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static int getExecutorMaxThreads(int originalMaxThreads) {
|
||||
if (originalMaxThreads != LITHO_LAYOUT_THREAD_POOL_SIZE) {
|
||||
Logger.printDebug(() -> "Overriding max thread pool size from: " + originalMaxThreads
|
||||
+ " to: " + LITHO_LAYOUT_THREAD_POOL_SIZE);
|
||||
}
|
||||
|
||||
return LITHO_LAYOUT_THREAD_POOL_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,8 +40,10 @@ public final class ShortsFilter extends Filter {
|
||||
|
||||
private static WeakReference<PivotBar> pivotBarRef = new WeakReference<>(null);
|
||||
|
||||
private final StringFilterGroup shortsCompactFeedVideoPath;
|
||||
private final StringFilterGroup shortsCompactFeedVideo;
|
||||
private final ByteArrayFilterGroup shortsCompactFeedVideoBuffer;
|
||||
private final StringFilterGroup useSoundButton;
|
||||
private final ByteArrayFilterGroup useSoundButtonBuffer;
|
||||
|
||||
private final StringFilterGroup subscribeButton;
|
||||
private final StringFilterGroup joinButton;
|
||||
@@ -49,11 +51,11 @@ public final class ShortsFilter extends Filter {
|
||||
private final StringFilterGroup shelfHeader;
|
||||
|
||||
private final StringFilterGroup suggestedAction;
|
||||
private final ByteArrayFilterGroupList suggestedActionsGroupList = new ByteArrayFilterGroupList();
|
||||
private final ByteArrayFilterGroupList suggestedActionsBuffer = new ByteArrayFilterGroupList();
|
||||
|
||||
private final StringFilterGroup shortsActionBar;
|
||||
private final StringFilterGroup actionButton;
|
||||
private final ByteArrayFilterGroupList videoActionButtonGroupList = new ByteArrayFilterGroupList();
|
||||
private final StringFilterGroup videoActionButton;
|
||||
private final ByteArrayFilterGroupList videoActionButtonBuffer = new ByteArrayFilterGroupList();
|
||||
|
||||
public ShortsFilter() {
|
||||
//
|
||||
@@ -82,7 +84,7 @@ public final class ShortsFilter extends Filter {
|
||||
// Path components.
|
||||
//
|
||||
|
||||
shortsCompactFeedVideoPath = new StringFilterGroup(null,
|
||||
shortsCompactFeedVideo = new StringFilterGroup(null,
|
||||
// Shorts that appear in the feed/search when the device is using tablet layout.
|
||||
"compact_video.eml",
|
||||
// 'video_lockup_with_attachment.eml' is shown instead of 'compact_video.eml' for some users
|
||||
@@ -174,7 +176,18 @@ public final class ShortsFilter extends Filter {
|
||||
"reel_action_bar.eml"
|
||||
);
|
||||
|
||||
actionButton = new StringFilterGroup(
|
||||
useSoundButton = new StringFilterGroup(
|
||||
Settings.HIDE_SHORTS_USE_SOUND_BUTTON,
|
||||
"floating_action_button.eml",
|
||||
REEL_METAPANEL_PATH
|
||||
);
|
||||
|
||||
useSoundButtonBuffer = new ByteArrayFilterGroup(
|
||||
null,
|
||||
"yt_outline_camera_"
|
||||
);
|
||||
|
||||
videoActionButton = new StringFilterGroup(
|
||||
null,
|
||||
// Can be simply 'button.eml', 'shorts_video_action_button.eml' or 'reel_action_button.eml'
|
||||
"button.eml"
|
||||
@@ -182,20 +195,21 @@ public final class ShortsFilter extends Filter {
|
||||
|
||||
suggestedAction = new StringFilterGroup(
|
||||
null,
|
||||
"suggested_action.eml"
|
||||
"suggested_action.eml",
|
||||
REEL_METAPANEL_PATH
|
||||
);
|
||||
|
||||
addPathCallbacks(
|
||||
shortsCompactFeedVideoPath, joinButton, subscribeButton, paidPromotionButton,
|
||||
shortsCompactFeedVideo, joinButton, subscribeButton, paidPromotionButton,
|
||||
shortsActionBar, suggestedAction, pausedOverlayButtons, channelBar,
|
||||
fullVideoLinkLabel, videoTitle, reelSoundMetadata, soundButton, infoPanel,
|
||||
fullVideoLinkLabel, videoTitle, useSoundButton, reelSoundMetadata, soundButton, infoPanel,
|
||||
stickers, likeFountain, likeButton, dislikeButton
|
||||
);
|
||||
|
||||
//
|
||||
// All other action buttons.
|
||||
//
|
||||
videoActionButtonGroupList.addAll(
|
||||
videoActionButtonBuffer.addAll(
|
||||
new ByteArrayFilterGroup(
|
||||
Settings.HIDE_SHORTS_COMMENTS_BUTTON,
|
||||
"reel_comment_button",
|
||||
@@ -216,7 +230,7 @@ public final class ShortsFilter extends Filter {
|
||||
//
|
||||
// Suggested actions.
|
||||
//
|
||||
suggestedActionsGroupList.addAll(
|
||||
suggestedActionsBuffer.addAll(
|
||||
new ByteArrayFilterGroup(
|
||||
Settings.HIDE_SHORTS_PREVIEW_COMMENT,
|
||||
// Preview comment that can popup while a Short is playing.
|
||||
@@ -242,10 +256,7 @@ public final class ShortsFilter extends Filter {
|
||||
"yt_outline_bookmark_",
|
||||
// 'Save sound' button. It seems this has been removed and only 'Save music' is used.
|
||||
// Still hide this in case it's still present.
|
||||
"yt_outline_list_add_",
|
||||
// 'Use this sound' button. It seems this has been removed and only 'Save music' is used.
|
||||
// Still hide this in case it's still present.
|
||||
"yt_outline_camera_"
|
||||
"yt_outline_list_add_"
|
||||
),
|
||||
new ByteArrayFilterGroup(
|
||||
Settings.HIDE_SHORTS_SEARCH_SUGGESTIONS,
|
||||
@@ -279,7 +290,7 @@ public final class ShortsFilter extends Filter {
|
||||
}
|
||||
|
||||
private boolean isEverySuggestedActionFilterEnabled() {
|
||||
for (ByteArrayFilterGroup group : suggestedActionsGroupList) {
|
||||
for (ByteArrayFilterGroup group : suggestedActionsBuffer) {
|
||||
if (!group.isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
@@ -297,15 +308,19 @@ public final class ShortsFilter extends Filter {
|
||||
return path.startsWith(REEL_CHANNEL_BAR_PATH) || path.startsWith(REEL_METAPANEL_PATH);
|
||||
}
|
||||
|
||||
if (matchedGroup == shortsCompactFeedVideoPath) {
|
||||
if (matchedGroup == useSoundButton) {
|
||||
return useSoundButtonBuffer.check(protobufBufferArray).isFiltered();
|
||||
}
|
||||
|
||||
if (matchedGroup == shortsCompactFeedVideo) {
|
||||
return shouldHideShortsFeedItems() && shortsCompactFeedVideoBuffer.check(protobufBufferArray).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 actionButton.check(path).isFiltered()
|
||||
&& videoActionButtonGroupList.check(protobufBufferArray).isFiltered();
|
||||
return videoActionButton.check(path).isFiltered()
|
||||
&& videoActionButtonBuffer.check(protobufBufferArray).isFiltered();
|
||||
}
|
||||
|
||||
if (matchedGroup == suggestedAction) {
|
||||
@@ -316,7 +331,7 @@ public final class ShortsFilter extends Filter {
|
||||
return true;
|
||||
}
|
||||
|
||||
return suggestedActionsGroupList.check(protobufBufferArray).isFiltered();
|
||||
return suggestedActionsBuffer.check(protobufBufferArray).isFiltered();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -64,10 +64,11 @@ public class RememberVideoQualityPatch {
|
||||
else videoQualityWifi.save(defaultQuality);
|
||||
networkTypeMessage = str("revanced_remember_video_quality_wifi");
|
||||
}
|
||||
Utils.showToastShort(str(
|
||||
useShortsPreference ? "revanced_remember_video_quality_toast_shorts" : "revanced_remember_video_quality_toast",
|
||||
networkTypeMessage, (defaultQuality + "p")
|
||||
));
|
||||
if (Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED_TOAST.get())
|
||||
Utils.showToastShort(str(
|
||||
useShortsPreference ? "revanced_remember_video_quality_toast_shorts" : "revanced_remember_video_quality_toast",
|
||||
networkTypeMessage, (defaultQuality + "p")
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -617,9 +617,9 @@ public class CustomPlaybackSpeedPatch {
|
||||
* @return The rounded speed, constrained to the specified bounds.
|
||||
*/
|
||||
private static float roundSpeedToNearestIncrement(float speed) {
|
||||
// Round to nearest 0.05 speed.
|
||||
final float roundedSpeed = Math.round(speed / 0.05f) * 0.05f;
|
||||
return Utils.clamp(roundedSpeed, 0.05f, PLAYBACK_SPEED_MAXIMUM);
|
||||
// Round to nearest 0.05 speed. Must use double precision otherwise rounding error can occur.
|
||||
final double roundedSpeed = Math.round(speed / 0.05) * 0.05;
|
||||
return Utils.clamp((float) roundedSpeed, 0.05f, PLAYBACK_SPEED_MAXIMUM);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -57,7 +57,8 @@ public final class RememberPlaybackSpeedPatch {
|
||||
}
|
||||
Settings.PLAYBACK_SPEED_DEFAULT.save(finalPlaybackSpeed);
|
||||
|
||||
Utils.showToastShort(str("revanced_remember_playback_speed_toast", (finalPlaybackSpeed + "x")));
|
||||
if (Settings.REMEMBER_PLAYBACK_SPEED_LAST_SELECTED_TOAST.get())
|
||||
Utils.showToastShort(str("revanced_remember_playback_speed_toast", (finalPlaybackSpeed + "x")));
|
||||
}, TOAST_DELAY_MILLISECONDS);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
|
||||
@@ -19,6 +19,7 @@ import android.widget.SearchView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -58,11 +59,7 @@ public class SearchViewController {
|
||||
GradientDrawable background = new GradientDrawable();
|
||||
background.setShape(GradientDrawable.RECTANGLE);
|
||||
background.setCornerRadius(28 * context.getResources().getDisplayMetrics().density); // 28dp corner radius.
|
||||
int baseColor = Utils.getAppBackgroundColor();
|
||||
int adjustedColor = Utils.isDarkModeEnabled()
|
||||
? Utils.adjustColorBrightness(baseColor, 1.11f) // Lighten for dark theme.
|
||||
: Utils.adjustColorBrightness(baseColor, 0.95f); // Darken for light theme.
|
||||
background.setColor(adjustedColor);
|
||||
background.setColor(getSearchViewBackground());
|
||||
return background;
|
||||
}
|
||||
|
||||
@@ -72,10 +69,17 @@ public class SearchViewController {
|
||||
private static GradientDrawable createSuggestionBackgroundDrawable(Context context) {
|
||||
GradientDrawable background = new GradientDrawable();
|
||||
background.setShape(GradientDrawable.RECTANGLE);
|
||||
background.setCornerRadius(8 * context.getResources().getDisplayMetrics().density); // 8dp corner radius.
|
||||
background.setColor(getSearchViewBackground());
|
||||
return background;
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
public static int getSearchViewBackground() {
|
||||
return Utils.isDarkModeEnabled()
|
||||
? Utils.adjustColorBrightness(Utils.getDialogBackgroundColor(), 1.11f)
|
||||
: Utils.adjustColorBrightness(Utils.getThemeLightColor(), 0.95f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds search view components to the activity.
|
||||
*/
|
||||
|
||||
@@ -52,6 +52,8 @@ public class Settings extends BaseSettings {
|
||||
public static final IntegerSetting VIDEO_QUALITY_DEFAULT_WIFI = new IntegerSetting("revanced_video_quality_default_wifi", -2);
|
||||
public static final IntegerSetting VIDEO_QUALITY_DEFAULT_MOBILE = new IntegerSetting("revanced_video_quality_default_mobile", -2);
|
||||
public static final BooleanSetting REMEMBER_VIDEO_QUALITY_LAST_SELECTED = new BooleanSetting("revanced_remember_video_quality_last_selected", FALSE);
|
||||
public static final BooleanSetting REMEMBER_VIDEO_QUALITY_LAST_SELECTED_TOAST = new BooleanSetting("revanced_remember_video_quality_last_selected_toast", TRUE, false,
|
||||
parent(REMEMBER_VIDEO_QUALITY_LAST_SELECTED));
|
||||
public static final IntegerSetting SHORTS_QUALITY_DEFAULT_WIFI = new IntegerSetting("revanced_shorts_quality_default_wifi", -2, true);
|
||||
public static final IntegerSetting SHORTS_QUALITY_DEFAULT_MOBILE = new IntegerSetting("revanced_shorts_quality_default_mobile", -2, true);
|
||||
public static final BooleanSetting REMEMBER_SHORTS_QUALITY_LAST_SELECTED = new BooleanSetting("revanced_remember_shorts_quality_last_selected", FALSE);
|
||||
@@ -60,6 +62,8 @@ public class Settings extends BaseSettings {
|
||||
// Speed
|
||||
public static final FloatSetting SPEED_TAP_AND_HOLD = new FloatSetting("revanced_speed_tap_and_hold", 2.0f, true);
|
||||
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 StringSetting CUSTOM_PLAYBACK_SPEEDS = new StringSetting("revanced_custom_playback_speeds",
|
||||
@@ -196,15 +200,16 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_TRANSCRIPT_SECTION = new BooleanSetting("revanced_hide_transcript_section", TRUE);
|
||||
// Action buttons
|
||||
public static final BooleanSetting DISABLE_LIKE_SUBSCRIBE_GLOW = new BooleanSetting("revanced_disable_like_subscribe_glow", FALSE);
|
||||
public static final BooleanSetting HIDE_ASK_BUTTON = new BooleanSetting("revanced_hide_ask_button", FALSE);
|
||||
public static final BooleanSetting HIDE_CLIP_BUTTON = new BooleanSetting("revanced_hide_clip_button", TRUE);
|
||||
public static final BooleanSetting HIDE_DOWNLOAD_BUTTON = new BooleanSetting("revanced_hide_download_button", FALSE);
|
||||
public static final BooleanSetting HIDE_LIKE_DISLIKE_BUTTON = new BooleanSetting("revanced_hide_like_dislike_button", FALSE);
|
||||
public static final BooleanSetting HIDE_PLAYLIST_BUTTON = new BooleanSetting("revanced_hide_playlist_button", FALSE);
|
||||
public static final BooleanSetting HIDE_REMIX_BUTTON = new BooleanSetting("revanced_hide_remix_button", TRUE);
|
||||
public static final BooleanSetting HIDE_REPORT_BUTTON = new BooleanSetting("revanced_hide_report_button", FALSE);
|
||||
public static final BooleanSetting HIDE_SAVE_BUTTON = new BooleanSetting("revanced_hide_save_button", FALSE);
|
||||
public static final BooleanSetting HIDE_SHARE_BUTTON = new BooleanSetting("revanced_hide_share_button", FALSE);
|
||||
public static final BooleanSetting HIDE_STOP_ADS_BUTTON = new BooleanSetting("revanced_hide_stop_ads_button", TRUE);
|
||||
public static final BooleanSetting HIDE_THANKS_BUTTON = new BooleanSetting("revanced_hide_thanks_button", TRUE);
|
||||
public static final BooleanSetting HIDE_ASK_BUTTON = new BooleanSetting("revanced_hide_ask_button", FALSE);
|
||||
// Player flyout menu items
|
||||
public static final BooleanSetting HIDE_PLAYER_FLYOUT_ADDITIONAL_SETTINGS = new BooleanSetting("revanced_hide_player_flyout_additional_settings", FALSE);
|
||||
public static final BooleanSetting HIDE_PLAYER_FLYOUT_AMBIENT_MODE = new BooleanSetting("revanced_hide_player_flyout_ambient_mode", FALSE);
|
||||
@@ -289,6 +294,7 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_SHORTS_SUPER_THANKS_BUTTON = new BooleanSetting("revanced_hide_shorts_super_thanks_button", TRUE);
|
||||
public static final BooleanSetting HIDE_SHORTS_TAGGED_PRODUCTS = new BooleanSetting("revanced_hide_shorts_tagged_products", TRUE);
|
||||
public static final BooleanSetting HIDE_SHORTS_UPCOMING_BUTTON = new BooleanSetting("revanced_hide_shorts_upcoming_button", TRUE);
|
||||
public static final BooleanSetting HIDE_SHORTS_USE_SOUND_BUTTON = new BooleanSetting("revanced_hide_shorts_use_sound_button", TRUE);
|
||||
public static final BooleanSetting HIDE_SHORTS_USE_TEMPLATE_BUTTON = new BooleanSetting("revanced_hide_shorts_use_template_button", TRUE);
|
||||
public static final BooleanSetting HIDE_SHORTS_VIDEO_TITLE = new BooleanSetting("revanced_hide_shorts_video_title", FALSE);
|
||||
public static final BooleanSetting SHORTS_AUTOPLAY = new BooleanSetting("revanced_shorts_autoplay", FALSE);
|
||||
|
||||
@@ -18,12 +18,7 @@ import android.text.TextWatcher;
|
||||
import android.util.Pair;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.GridLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.RadioGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.*;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
|
||||
@@ -88,8 +83,6 @@ public class SegmentCategoryListPreference extends ListPreference {
|
||||
// Create the main layout for the dialog content.
|
||||
LinearLayout contentLayout = new LinearLayout(context);
|
||||
contentLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
final int dip10 = dipToPixels(10);
|
||||
contentLayout.setPadding(0, 0, 0, dip10);
|
||||
|
||||
// Add behavior selection radio buttons.
|
||||
RadioGroup radioGroup = new RadioGroup(context);
|
||||
@@ -103,7 +96,7 @@ public class SegmentCategoryListPreference extends ListPreference {
|
||||
radioGroup.addView(radioButton);
|
||||
}
|
||||
radioGroup.setOnCheckedChangeListener((group, checkedId) -> selectedDialogEntryIndex = checkedId);
|
||||
radioGroup.setPadding(dip10, 0, 0, 0);
|
||||
radioGroup.setPadding(dipToPixels(10), 0, 0, 0);
|
||||
contentLayout.addView(radioGroup);
|
||||
|
||||
// Inflate the color picker view.
|
||||
@@ -131,7 +124,7 @@ public class SegmentCategoryListPreference extends ListPreference {
|
||||
gridParams = new GridLayout.LayoutParams();
|
||||
gridParams.rowSpec = GridLayout.spec(0); // First row.
|
||||
gridParams.columnSpec = GridLayout.spec(1); // Second column.
|
||||
gridParams.setMargins(0, 0, dip10, 0);
|
||||
gridParams.setMargins(0, 0, dipToPixels(10), 0);
|
||||
dialogColorDotView = new TextView(context);
|
||||
dialogColorDotView.setLayoutParams(gridParams);
|
||||
gridLayout.addView(dialogColorDotView);
|
||||
@@ -250,20 +243,17 @@ public class SegmentCategoryListPreference extends ListPreference {
|
||||
|
||||
contentLayout.addView(gridLayout);
|
||||
|
||||
// Set up color picker listener.
|
||||
// Do last to prevent listener callbacks while setting up view.
|
||||
dialogColorPickerView.setOnColorChangedListener(color -> {
|
||||
if (categoryColor == color) {
|
||||
return;
|
||||
}
|
||||
categoryColor = color;
|
||||
String hexColor = getColorString(color);
|
||||
Logger.printDebug(() -> "onColorChanged: " + hexColor);
|
||||
|
||||
updateCategoryColorDot();
|
||||
dialogColorEditText.setText(hexColor);
|
||||
dialogColorEditText.setSelection(hexColor.length());
|
||||
});
|
||||
// Create ScrollView to wrap the content layout.
|
||||
ScrollView contentScrollView = new ScrollView(context);
|
||||
contentScrollView.setVerticalScrollBarEnabled(false); // Disable vertical scrollbar.
|
||||
contentScrollView.setOverScrollMode(View.OVER_SCROLL_NEVER); // Disable overscroll effect.
|
||||
LinearLayout.LayoutParams scrollViewParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
0,
|
||||
1.0f
|
||||
);
|
||||
contentScrollView.setLayoutParams(scrollViewParams);
|
||||
contentScrollView.addView(contentLayout);
|
||||
|
||||
// Create the custom dialog.
|
||||
Pair<Dialog, LinearLayout> dialogPair = Utils.createCustomDialog(
|
||||
@@ -309,13 +299,27 @@ public class SegmentCategoryListPreference extends ListPreference {
|
||||
false // Do not dismiss dialog on Neutral button click.
|
||||
);
|
||||
|
||||
dialog = dialogPair.first;
|
||||
// Add the ScrollView to the dialog's main layout.
|
||||
LinearLayout dialogMainLayout = dialogPair.second;
|
||||
dialogMainLayout.addView(contentScrollView, dialogMainLayout.getChildCount() - 1);
|
||||
|
||||
// Add the custom content to the dialog's main layout.
|
||||
dialogMainLayout.addView(contentLayout, 1); // Add after title, before buttons.
|
||||
// Set up color picker listener.
|
||||
// Do last to prevent listener callbacks while setting up view.
|
||||
dialogColorPickerView.setOnColorChangedListener(color -> {
|
||||
if (categoryColor == color) {
|
||||
return;
|
||||
}
|
||||
categoryColor = color;
|
||||
String hexColor = getColorString(color);
|
||||
Logger.printDebug(() -> "onColorChanged: " + hexColor);
|
||||
|
||||
updateCategoryColorDot();
|
||||
dialogColorEditText.setText(hexColor);
|
||||
dialogColorEditText.setSelection(hexColor.length());
|
||||
});
|
||||
|
||||
// Show the dialog.
|
||||
dialog = dialogPair.first;
|
||||
dialog.show();
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "showDialog failure", ex);
|
||||
|
||||
@@ -42,7 +42,6 @@ public class PlaybackSpeedDialogButton {
|
||||
: Settings.PLAYBACK_SPEED_DEFAULT.get();
|
||||
|
||||
VideoInformation.overridePlaybackSpeed(speed);
|
||||
showToastShort(str("revanced_custom_playback_speeds_reset_toast", (speed + "x")));
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "speed button reset failure", ex);
|
||||
}
|
||||
|
||||
@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
|
||||
org.gradle.parallel = true
|
||||
android.useAndroidX = true
|
||||
kotlin.code.style = official
|
||||
version = 5.28.0-dev.5
|
||||
version = 5.29.0-dev.7
|
||||
|
||||
@@ -160,6 +160,10 @@ public final class app/revanced/patches/cieid/restrictions/root/BypassRootChecks
|
||||
public static final fun getBypassRootChecksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/crunchyroll/ads/HideAdsPatchKt {
|
||||
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/duolingo/ad/DisableAdsPatchKt {
|
||||
public static final fun getDisableAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -958,6 +962,10 @@ public final class app/revanced/patches/swissid/integritycheck/RemoveGooglePlayI
|
||||
public static final fun getRemoveGooglePlayIntegrityCheckPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/threads/HideAdsPatchKt {
|
||||
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/ticktick/misc/themeunlock/UnlockThemePatchKt {
|
||||
public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package app.revanced.patches.crunchyroll.ads
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal val videoUrlReadyToStringFingerprint = fingerprint {
|
||||
strings("VideoUrlReady(url=", ", enableAds=")
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package app.revanced.patches.crunchyroll.ads
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.removeFlags
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
@Suppress("unused")
|
||||
val hideAdsPatch = bytecodePatch(
|
||||
name = "Hide Ads"
|
||||
) {
|
||||
compatibleWith("com.crunchyroll.crunchyroid")
|
||||
|
||||
execute {
|
||||
// Get obfuscated "enableAds" field from toString method.
|
||||
val enableAdsField = videoUrlReadyToStringFingerprint.let {
|
||||
val strIndex = videoUrlReadyToStringFingerprint.stringMatches!!.last().index
|
||||
val fieldIndex = it.method.indexOfFirstInstruction(strIndex, Opcode.IGET_BOOLEAN)
|
||||
it.method.getInstruction<ReferenceInstruction>(fieldIndex).getReference<FieldReference>()!!
|
||||
}
|
||||
|
||||
// Remove final access flag on field.
|
||||
videoUrlReadyToStringFingerprint.classDef.fields
|
||||
.first { it.name == enableAdsField.name }
|
||||
.removeFlags(AccessFlags.FINAL)
|
||||
|
||||
// Override enableAds field in non-default constructor.
|
||||
val constructor = videoUrlReadyToStringFingerprint.classDef.methods.first {
|
||||
AccessFlags.CONSTRUCTOR.isSet(it.accessFlags) && it.parameters.isNotEmpty()
|
||||
}
|
||||
constructor.addInstructions(
|
||||
constructor.instructions.count() - 1,
|
||||
"""
|
||||
move-object/from16 v0, p0
|
||||
const/4 v1, 0x0
|
||||
iput-boolean v1, v0, $enableAdsField
|
||||
""")
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,16 @@
|
||||
package app.revanced.patches.instagram.ads
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.meta.ads.adInjectorFingerprint
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Deprecated("Patch was moved to different package: app.revanced.patches.meta.ads.hideAdsPatch")
|
||||
@Suppress("unused")
|
||||
val hideAdsPatch = bytecodePatch {
|
||||
dependsOn(app.revanced.patches.meta.ads.hideAdsPatch)
|
||||
val hideAdsPatch = bytecodePatch(
|
||||
name = "Hide ads",
|
||||
) {
|
||||
compatibleWith("com.instagram.android")
|
||||
|
||||
execute {
|
||||
adInjectorFingerprint.method.returnEarly(false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,3 +11,15 @@ internal val getMobileConfigBoolFingerprint = fingerprint {
|
||||
classDef.interfaces.contains("Lcom/facebook/mobileconfig/factory/MobileConfigUnsafeContext;")
|
||||
}
|
||||
}
|
||||
|
||||
internal val metaAIKillSwitchCheckFingerprint = fingerprint {
|
||||
strings("SearchAiagentImplementationsKillSwitch")
|
||||
opcodes(Opcode.CONST_WIDE)
|
||||
}
|
||||
|
||||
internal val extensionMethodFingerprint = fingerprint {
|
||||
strings("REPLACED_BY_PATCH")
|
||||
custom { method, classDef ->
|
||||
method.name == EXTENSION_METHOD_NAME && classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,14 @@ package app.revanced.patches.messenger.metaai
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.messenger.misc.extension.sharedExtensionPatch
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/messenger/metaai/RemoveMetaAIPatch;"
|
||||
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/messenger/metaai/RemoveMetaAIPatch;"
|
||||
internal const val EXTENSION_METHOD_NAME = "overrideBooleanFlag"
|
||||
|
||||
@Suppress("unused")
|
||||
val removeMetaAIPatch = bytecodePatch(
|
||||
@@ -25,10 +28,25 @@ val removeMetaAIPatch = bytecodePatch(
|
||||
addInstructions(
|
||||
returnIndex,
|
||||
"""
|
||||
invoke-static { p1, p2, v$returnRegister }, $EXTENSION_CLASS_DESCRIPTOR->overrideBooleanFlag(JZ)Z
|
||||
invoke-static { p1, p2, v$returnRegister }, $EXTENSION_CLASS_DESCRIPTOR->$EXTENSION_METHOD_NAME(JZ)Z
|
||||
move-result v$returnRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
// Extract the common starting digits of Meta AI flag IDs from a flag found in code.
|
||||
val relevantDigits = with(metaAIKillSwitchCheckFingerprint) {
|
||||
method.getInstruction<WideLiteralInstruction>(patternMatch!!.startIndex).wideLiteral
|
||||
}.toString().substring(0, 7)
|
||||
|
||||
// Replace placeholder in the extension method.
|
||||
with(extensionMethodFingerprint) {
|
||||
method.replaceInstruction(
|
||||
stringMatches!!.first().index,
|
||||
"""
|
||||
const-string v1, "$relevantDigits"
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,4 +2,4 @@ package app.revanced.patches.messenger.misc.extension
|
||||
|
||||
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
|
||||
|
||||
val sharedExtensionPatch = sharedExtensionPatch("messenger", mainActivityOnCreateHook)
|
||||
val sharedExtensionPatch = sharedExtensionPatch("messenger", messengerApplicationOnCreateHook)
|
||||
|
||||
@@ -2,6 +2,8 @@ package app.revanced.patches.messenger.misc.extension
|
||||
|
||||
import app.revanced.patches.shared.misc.extension.extensionHook
|
||||
|
||||
internal val mainActivityOnCreateHook = extensionHook {
|
||||
strings("MainActivity_onCreate_begin")
|
||||
internal val messengerApplicationOnCreateHook = extensionHook {
|
||||
custom { method, classDef ->
|
||||
method.name == "onCreate" && classDef.endsWith("/MessengerApplication;")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,18 +3,9 @@ package app.revanced.patches.meta.ads
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Deprecated("Instead use the Instagram or Threads specific hide ads patch")
|
||||
@Suppress("unused")
|
||||
val hideAdsPatch = bytecodePatch(
|
||||
name = "Hide ads",
|
||||
) {
|
||||
/**
|
||||
* Patch is identical for both Instagram and Threads app.
|
||||
*/
|
||||
compatibleWith(
|
||||
"com.instagram.android",
|
||||
"com.instagram.barcelona",
|
||||
)
|
||||
|
||||
val hideAdsPatch = bytecodePatch {
|
||||
execute {
|
||||
adInjectorFingerprint.method.returnEarly(false)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package app.revanced.patches.threads
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.meta.ads.adInjectorFingerprint
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
val hideAdsPatch = bytecodePatch(
|
||||
name = "Hide ads",
|
||||
) {
|
||||
compatibleWith("com.instagram.barcelona"("382.0.0.51.85"))
|
||||
|
||||
execute {
|
||||
adInjectorFingerprint.method.returnEarly(false)
|
||||
}
|
||||
}
|
||||
@@ -77,8 +77,6 @@ val hideAdsPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -25,8 +25,6 @@ val hideGetPremiumPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -23,8 +23,6 @@ val videoAdsPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -53,8 +53,6 @@ val copyVideoUrlPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -24,8 +24,6 @@ val removeViewerDiscretionDialogPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -72,8 +72,6 @@ val downloadsPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -20,8 +20,6 @@ val seekbarPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -18,8 +18,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/SeekbarThumbnailsPatch;"
|
||||
|
||||
val seekbarThumbnailsPatch = bytecodePatch(
|
||||
description = "Adds an option to use high quality fullscreen seekbar thumbnails. " +
|
||||
"Patching 19.16.39 adds an option to restore old seekbar thumbnails.",
|
||||
description = "Adds an option to use high quality fullscreen seekbar thumbnails."
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
|
||||
@@ -88,8 +88,6 @@ val swipeControlsPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -24,8 +24,6 @@ val autoCaptionsPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -43,8 +43,6 @@ val customBrandingPatch = resourcePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -41,8 +41,6 @@ val changeHeaderPatch = resourcePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -22,8 +22,6 @@ val hideButtonsPatch = resourcePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
@@ -40,15 +38,16 @@ val hideButtonsPatch = resourcePatch(
|
||||
"revanced_hide_buttons_screen",
|
||||
preferences = setOf(
|
||||
SwitchPreference("revanced_disable_like_subscribe_glow"),
|
||||
SwitchPreference("revanced_hide_like_dislike_button"),
|
||||
SwitchPreference("revanced_hide_share_button"),
|
||||
SwitchPreference("revanced_hide_report_button"),
|
||||
SwitchPreference("revanced_hide_remix_button"),
|
||||
SwitchPreference("revanced_hide_download_button"),
|
||||
SwitchPreference("revanced_hide_thanks_button"),
|
||||
SwitchPreference("revanced_hide_ask_button"),
|
||||
SwitchPreference("revanced_hide_clip_button"),
|
||||
SwitchPreference("revanced_hide_playlist_button"),
|
||||
SwitchPreference("revanced_hide_download_button"),
|
||||
SwitchPreference("revanced_hide_like_dislike_button"),
|
||||
SwitchPreference("revanced_hide_remix_button"),
|
||||
SwitchPreference("revanced_hide_report_button"),
|
||||
SwitchPreference("revanced_hide_save_button"),
|
||||
SwitchPreference("revanced_hide_share_button"),
|
||||
SwitchPreference("revanced_hide_stop_ads_button"),
|
||||
SwitchPreference("revanced_hide_thanks_button"),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -40,8 +40,6 @@ val navigationButtonsPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -58,8 +58,6 @@ val hidePlayerOverlayButtonsPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -33,8 +33,6 @@ val changeFormFactorPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -59,8 +59,6 @@ val hideEndscreenCardsPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -31,8 +31,6 @@ val hideEndScreenSuggestedVideoPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -29,8 +29,6 @@ val disableFullscreenAmbientModePatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -125,8 +125,6 @@ val hideLayoutComponentsPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -57,8 +57,6 @@ val hideInfoCardsPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -24,8 +24,6 @@ val hidePlayerFlyoutMenuPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -48,8 +48,6 @@ val hideRelatedVideoOverlayPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -29,8 +29,6 @@ val disableRollingNumberAnimationPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -94,6 +94,7 @@ private val hideShortsComponentsResourcePatch = resourcePatch {
|
||||
// Suggested actions.
|
||||
SwitchPreference("revanced_hide_shorts_preview_comment"),
|
||||
SwitchPreference("revanced_hide_shorts_save_sound_button"),
|
||||
SwitchPreference("revanced_hide_shorts_use_sound_button"),
|
||||
SwitchPreference("revanced_hide_shorts_use_template_button"),
|
||||
SwitchPreference("revanced_hide_shorts_upcoming_button"),
|
||||
SwitchPreference("revanced_hide_shorts_green_screen_button"),
|
||||
@@ -170,8 +171,6 @@ val hideShortsComponentsPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -21,8 +21,6 @@ val hideTimestampPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -153,22 +153,6 @@ val miniplayerPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39", // First with modern miniplayers.
|
||||
// 19.17.41 // Works without issues, but no reason to recommend over 19.16.
|
||||
// 19.18.41 // Works without issues, but no reason to recommend over 19.16.
|
||||
// 19.19.39 // Last bug free version with smaller Modern 1 miniplayer, but no reason to recommend over 19.16.
|
||||
// 19.20.35 // Cannot swipe to expand.
|
||||
// 19.21.40 // Cannot swipe to expand.
|
||||
// 19.22.43 // Cannot swipe to expand.
|
||||
// 19.23.40 // First with Modern 1 drag and drop, Cannot swipe to expand.
|
||||
// 19.24.45 // First with larger Modern 1, Cannot swipe to expand.
|
||||
"19.25.37", // First with double tap, last with skip forward/back buttons, last with swipe to expand/close, and last before double tap to expand seems to be required.
|
||||
// 19.26.42 // Modern 1 Pause/play button are always hidden. Unusable.
|
||||
// 19.28.42 // First with custom miniplayer size, screen flickers when swiping to maximize Modern 1. Swipe to close miniplayer is broken.
|
||||
// 19.29.42 // All modern players are broken and ignore tapping the miniplayer video.
|
||||
// 19.30.39 // Modern 3 is less broken when double tap expand is enabled, but cannot swipe to expand when double tap is off.
|
||||
// 19.31.36 // All Modern 1 buttons are missing. Unusable.
|
||||
// 19.32.36 // 19.32+ and beyond all work without issues.
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -21,8 +21,6 @@ val playerPopupPanelsPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -21,8 +21,6 @@ internal val exitFullscreenPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -52,8 +52,6 @@ val customPlayerOverlayOpacityPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -61,8 +61,6 @@ val returnYouTubeDislikePatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -66,8 +66,6 @@ val wideSearchbarPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -44,8 +44,6 @@ val shortsAutoplayPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -64,8 +64,6 @@ val openShortsInRegularPlayerPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -126,8 +126,6 @@ val sponsorBlockPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -58,8 +58,6 @@ val spoofAppVersionPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -32,8 +32,6 @@ val changeStartPagePatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -34,8 +34,6 @@ val disableResumingShortsOnStartupPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -204,8 +204,6 @@ val themePatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -33,8 +33,6 @@ val alternativeThumbnailsPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -27,8 +27,6 @@ val bypassImageRegionRestrictionsPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -23,8 +23,6 @@ val announcementsPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -24,8 +24,6 @@ val autoRepeatPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -51,8 +51,6 @@ val backgroundPlaybackPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -35,8 +35,6 @@ val enableDebuggingPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -24,8 +24,6 @@ val spoofDeviceDimensionsPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -21,8 +21,6 @@ val checkWatchHistoryDomainNameResolutionPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -35,8 +35,6 @@ val gmsCoreSupportPatch = gmsCoreSupportPatch(
|
||||
|
||||
compatibleWith(
|
||||
YOUTUBE_PACKAGE_NAME(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -26,8 +26,6 @@ val disableHapticFeedbackPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -32,8 +32,6 @@ val bypassURLRedirectsPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -41,8 +41,6 @@ val openLinksExternallyPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.revanced.patches.youtube.misc.litho.filter
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.containsLiteralInstruction
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
@@ -52,6 +53,15 @@ internal val emptyComponentFingerprint = fingerprint {
|
||||
}
|
||||
}
|
||||
|
||||
internal val lithoThreadExecutorFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
parameters("I", "I", "I")
|
||||
custom { method, classDef ->
|
||||
classDef.superclass == "Ljava/util/concurrent/ThreadPoolExecutor;" &&
|
||||
method.containsLiteralInstruction(1L) // 1L = default thread timeout.
|
||||
}
|
||||
}
|
||||
|
||||
internal val lithoComponentNameUpbFeatureFlagFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("Z")
|
||||
|
||||
@@ -209,6 +209,22 @@ val lithoFilterPatch = bytecodePatch(
|
||||
|
||||
// endregion
|
||||
|
||||
|
||||
// region Change Litho thread executor to 1 thread to fix layout issue in unpatched YouTube.
|
||||
|
||||
lithoThreadExecutorFingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->getExecutorCorePoolSize(I)I
|
||||
move-result p1
|
||||
invoke-static { p2 }, $EXTENSION_CLASS_DESCRIPTOR->getExecutorMaxThreads(I)I
|
||||
move-result p2
|
||||
"""
|
||||
)
|
||||
|
||||
// endregion
|
||||
|
||||
|
||||
// region A/B test of new Litho native code.
|
||||
|
||||
// Turn off native code that handles litho component names. If this feature is on then nearly
|
||||
|
||||
@@ -5,29 +5,37 @@ package app.revanced.patches.youtube.misc.playservice
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.util.findElementByAttributeValueOrThrow
|
||||
|
||||
@Deprecated("19.16.39 is the lowest supported version")
|
||||
@Deprecated("19.34.42 is the lowest supported version")
|
||||
var is_19_03_or_greater = false
|
||||
private set
|
||||
@Deprecated("19.16.39 is the lowest supported version")
|
||||
@Deprecated("19.34.42 is the lowest supported version")
|
||||
var is_19_04_or_greater = false
|
||||
private set
|
||||
@Deprecated("19.16.39 is the lowest supported version")
|
||||
@Deprecated("19.34.42 is the lowest supported version")
|
||||
var is_19_16_or_greater = false
|
||||
private set
|
||||
@Deprecated("19.34.42 is the lowest supported version")
|
||||
var is_19_17_or_greater = false
|
||||
private set
|
||||
@Deprecated("19.34.42 is the lowest supported version")
|
||||
var is_19_18_or_greater = false
|
||||
private set
|
||||
@Deprecated("19.34.42 is the lowest supported version")
|
||||
var is_19_23_or_greater = false
|
||||
private set
|
||||
@Deprecated("19.34.42 is the lowest supported version")
|
||||
var is_19_25_or_greater = false
|
||||
private set
|
||||
@Deprecated("19.34.42 is the lowest supported version")
|
||||
var is_19_26_or_greater = false
|
||||
private set
|
||||
@Deprecated("19.34.42 is the lowest supported version")
|
||||
var is_19_29_or_greater = false
|
||||
private set
|
||||
@Deprecated("19.34.42 is the lowest supported version")
|
||||
var is_19_32_or_greater = false
|
||||
private set
|
||||
@Deprecated("19.34.42 is the lowest supported version")
|
||||
var is_19_33_or_greater = false
|
||||
private set
|
||||
var is_19_34_or_greater = false
|
||||
|
||||
@@ -30,8 +30,6 @@ val removeTrackingQueryParameterPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -17,8 +17,6 @@ import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
val spoofVideoStreamsPatch = spoofVideoStreamsPatch({
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -41,8 +41,6 @@ val forceOriginalAudioPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -28,8 +28,6 @@ val disableHdrPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -57,7 +57,8 @@ val rememberVideoQualityPatch = bytecodePatch {
|
||||
entriesKey = "revanced_shorts_quality_default_entries",
|
||||
entryValuesKey = "revanced_shorts_quality_default_entry_values"
|
||||
),
|
||||
SwitchPreference("revanced_remember_shorts_quality_last_selected")
|
||||
SwitchPreference("revanced_remember_shorts_quality_last_selected"),
|
||||
SwitchPreference("revanced_remember_video_quality_last_selected_toast")
|
||||
))
|
||||
|
||||
/*
|
||||
|
||||
@@ -23,8 +23,6 @@ val videoQualityPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -28,8 +28,6 @@ val playbackSpeedPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.16.39",
|
||||
"19.25.37",
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
|
||||
@@ -39,7 +39,8 @@ internal val rememberPlaybackSpeedPatch = bytecodePatch {
|
||||
entryValuesKey = null,
|
||||
tag = "app.revanced.extension.youtube.settings.preference.CustomVideoSpeedListPreference"
|
||||
),
|
||||
SwitchPreference("revanced_remember_playback_speed_last_selected")
|
||||
SwitchPreference("revanced_remember_playback_speed_last_selected"),
|
||||
SwitchPreference("revanced_remember_playback_speed_last_selected_toast")
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableField
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
@@ -1011,8 +1012,8 @@ private fun MutableMethod.overrideReturnValue(value: String, returnLate: Boolean
|
||||
}
|
||||
|
||||
if (returnLate) {
|
||||
findInstructionIndicesReversed {
|
||||
opcode == RETURN || opcode == RETURN_OBJECT
|
||||
findInstructionIndicesReversedOrThrow {
|
||||
opcode == RETURN || opcode == RETURN_WIDE || opcode == RETURN_OBJECT
|
||||
}.forEach { index ->
|
||||
addInstructionsAtControlFlowLabel(index, instructions)
|
||||
}
|
||||
@@ -1021,6 +1022,14 @@ private fun MutableMethod.overrideReturnValue(value: String, returnLate: Boolean
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the given AccessFlags from the field.
|
||||
*/
|
||||
internal fun MutableField.removeFlags(vararg flags: AccessFlags) {
|
||||
val bitField = flags.map { it.value }.reduce { acc, flag -> acc and flag }
|
||||
this.accessFlags = this.accessFlags and bitField.inv()
|
||||
}
|
||||
|
||||
internal fun BytecodePatchContext.addStaticFieldToExtension(
|
||||
className: String,
|
||||
methodName: String,
|
||||
|
||||
@@ -79,6 +79,7 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.buttons.action.hideButtonsPatch">
|
||||
<!-- 'Share' should be translated with the same localized wording that YouTube displays. -->
|
||||
<!-- 'Stop ads' should be translated with the same localized wording that YouTube displays. -->
|
||||
<!-- 'Report' should be translated with the same localized wording that YouTube displays.
|
||||
This button usually appears only on live streams. -->
|
||||
<!-- 'Remix' should be translated with the same localized wording that YouTube displays. -->
|
||||
|
||||
@@ -79,6 +79,7 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.buttons.action.hideButtonsPatch">
|
||||
<!-- 'Share' should be translated with the same localized wording that YouTube displays. -->
|
||||
<!-- 'Stop ads' should be translated with the same localized wording that YouTube displays. -->
|
||||
<!-- 'Report' should be translated with the same localized wording that YouTube displays.
|
||||
This button usually appears only on live streams. -->
|
||||
<!-- 'Remix' should be translated with the same localized wording that YouTube displays. -->
|
||||
|
||||
@@ -35,7 +35,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_settings_submenu_title">الإعدادات</string>
|
||||
<string name="revanced_settings_confirm_user_dialog_title">هل أنت متأكد أنك تريد المتابعة؟</string>
|
||||
<string name="revanced_settings_reset">إعادة التعيين</string>
|
||||
<string name="revanced_settings_reset_color">Reset color</string>
|
||||
<string name="revanced_settings_reset_color">إعادة تعيين اللون</string>
|
||||
<string name="revanced_settings_color_invalid">لون غير صالح</string>
|
||||
<string name="revanced_settings_restart_title">إعادة التشغيل مطلوبة</string>
|
||||
<string name="revanced_settings_restart_dialog_message">أعد تشغيل التطبيق لكي يسري هذا التغيير.</string>
|
||||
@@ -533,6 +533,10 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_share_button_title">إخفاء المشاركة</string>
|
||||
<string name="revanced_hide_share_button_summary_on">تم إخفاء زر مشاركة</string>
|
||||
<string name="revanced_hide_share_button_summary_off">يتم عرض زر مشاركة</string>
|
||||
<!-- 'Stop ads' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_stop_ads_button_title">إخفاء إيقاف الإعلانات</string>
|
||||
<string name="revanced_hide_stop_ads_button_summary_on">زر إيقاف الإعلانات مخفي</string>
|
||||
<string name="revanced_hide_stop_ads_button_summary_off">زر إيقاف الإعلانات معروض</string>
|
||||
<!-- 'Report' should be translated with the same localized wording that YouTube displays.
|
||||
This button usually appears only on live streams. -->
|
||||
<string name="revanced_hide_report_button_title">إخفاء الإبلاغ</string>
|
||||
@@ -560,9 +564,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_clip_button_summary_on">تم إخفاء زر إنشاء مقطع</string>
|
||||
<string name="revanced_hide_clip_button_summary_off">يتم عرض زر إنشاء مقطع</string>
|
||||
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_playlist_button_title">إخفاء الحفظ في قائمة التشغيل</string>
|
||||
<string name="revanced_hide_playlist_button_summary_on">تم إخفاء زر الحفظ في قائمة التشغيل</string>
|
||||
<string name="revanced_hide_playlist_button_summary_off">يتم عرض زر الحفظ في قائمة التشغيل</string>
|
||||
<string name="revanced_hide_save_button_title">إخفاء حفظ</string>
|
||||
<string name="revanced_hide_save_button_summary_on">زر الحفظ مخفي</string>
|
||||
<string name="revanced_hide_save_button_summary_off">زر الحفظ معروض</string>
|
||||
</patch>
|
||||
<patch id="layout.buttons.navigation.navigationButtonsPatch">
|
||||
<string name="revanced_navigation_buttons_screen_title">أزرار التنقل</string>
|
||||
@@ -760,9 +764,12 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_shorts_save_sound_button_title">إخفاء زر حفظ الموسيقى</string>
|
||||
<string name="revanced_hide_shorts_save_sound_button_summary_on">تم إخفاء زر حفظ الموسيقى</string>
|
||||
<string name="revanced_hide_shorts_save_sound_button_summary_off">يتم عرض زر حفظ الموسيقى</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_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_summary_on">زر استخدام هذا القالب مخفي</string>
|
||||
<string name="revanced_hide_shorts_use_template_button_summary_off">زر استخدام هذا القالب ظاهر</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_title">إخفاء زر القادم</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_summary_on">تم إخفاء زر القادم</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_summary_off">يتم عرض زر القادم</string>
|
||||
@@ -921,8 +928,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_seekbar_thumbnails_high_quality_title">تمكين المصغرات عالية الجودة</string>
|
||||
<string name="revanced_seekbar_thumbnails_high_quality_summary_on">مصغرات شريط التقدم عالية الجودة</string>
|
||||
<string name="revanced_seekbar_thumbnails_high_quality_summary_off">مصغرات شريط التقدم متوسطة الجودة</string>
|
||||
<string name="revanced_seekbar_thumbnails_high_quality_legacy_summary_on">مصغرات شريط التقدم بملء الشاشة عالية الجودة</string>
|
||||
<string name="revanced_seekbar_thumbnails_high_quality_legacy_summary_off">مصغرات شريط التقدم بملء الشاشة متوسطة الجودة</string>
|
||||
<string name="revanced_seekbar_thumbnails_high_quality_dialog_message">"سيؤدي هذا أيضا إلى استعادة المصغرات على البث المباشر الذي لا يحتوي على مصغرات شريط التقدم.
|
||||
|
||||
مصغرات شريط التقدم سوف تستخدم نفس جودة الفيديو الحالي.
|
||||
@@ -1009,7 +1014,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_sb_segments_highlight_sum">الجزء من الفيديو الذي يبحث عنه معظم الناس</string>
|
||||
<string name="revanced_sb_segments_intro">المقدمة/فاصل</string>
|
||||
<string name="revanced_sb_segments_intro_sum">فاصل زمني بدون محتوى فعلي. قد يكون توقفًا مؤقتًا، أو إطارًا ثابتًا، أو رسومًا متحركة متكررة. لا يتضمن انتقالات تحتوي على معلومات</string>
|
||||
<string name="revanced_sb_segments_outro">الخاتمة/تترات النهاية</string>
|
||||
<string name="revanced_sb_segments_outro">الخاتمة / تترات النهاية</string>
|
||||
<string name="revanced_sb_segments_outro_sum">تتر النهاية أو عندما تظهر بطاقات نهاية YouTube، نهايات غير منطوقة. ليس للاستنتاجات مع المعلومات</string>
|
||||
<string name="revanced_sb_segments_preview">معاينة/موجز/ربط</string>
|
||||
<string name="revanced_sb_segments_preview_sum">مجموعة من المقاطع التي توضح ما هو قادم أو ما حدث في الفيديو أو في مقاطع فيديو أخرى من السلسلة، حيث تتكرر جميع المعلومات في مكان آخر</string>
|
||||
@@ -1131,7 +1136,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_change_form_factor_entry_1">الافتراضي</string>
|
||||
<string name="revanced_change_form_factor_entry_2">الجوّال</string>
|
||||
<string name="revanced_change_form_factor_entry_3">الجهاز اللوحي</string>
|
||||
<string name="revanced_change_form_factor_entry_4">Automotive</string>
|
||||
<string name="revanced_change_form_factor_user_dialog_message">"التغييرات تشمل:
|
||||
|
||||
تصميم الجهاز اللوحي
|
||||
@@ -1241,11 +1245,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_title">إخفاء أزرار الواجهة</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_summary_on">تم إخفاء أزرار الواجهة</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_summary_off">يتم عرض أزرار الواجهة</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_legacy_title">إخفاء زري التوسيع والإغلاق</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_legacy_summary_on">"تم إخفاء الأزرار
|
||||
|
||||
اسحب للتوسيع أو الإغلاق"</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_legacy_summary_off">يتم عرض زري التوسيع والإغلاق</string>
|
||||
<string name="revanced_miniplayer_hide_subtext_title">إخفاء النصوص الفرعية</string>
|
||||
<string name="revanced_miniplayer_hide_subtext_summary_on">تم إخفاء النصوص الفرعية</string>
|
||||
<string name="revanced_miniplayer_hide_subtext_summary_off">يتم عرض النصوص الفرعية</string>
|
||||
@@ -1303,8 +1302,8 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_connection_toast_title">عرض ملاحظة إذا كان API غير متاح</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_on">يتم عرض ملاحظة إذا كان DeArrow غير متوفر</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_off">لا يتم عرض ملاحظة إذا كان DeArrow غير متوفر</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_api_url_title">DeArrow API endpoint</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_api_url_summary">The URL of the DeArrow thumbnail cache endpoint</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_api_url_title">نقطة نهاية واجهة برمجة تطبيقات DeArrow</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_api_url_summary">عنوان URL لنقطة نهاية ذاكرة التخزين المؤقت للصور المصغرة لـ DeArrow</string>
|
||||
<string name="revanced_alt_thumbnail_stills_about_title">لقطات الفيديو الثابتة</string>
|
||||
<string name="revanced_alt_thumbnail_stills_about_summary">يتم التقاط اللقطات الثابتة من بداية/وسط/نهاية كل فيديو. هذه الصور مدمجة في YouTube ولا يتم استخدام أي واجهة برمجة تطبيقات خارجية</string>
|
||||
<string name="revanced_alt_thumbnail_stills_fast_title">استخدم اللقطات الثابتة السريعة</string>
|
||||
@@ -1397,6 +1396,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_title">تذكر تغييرات جودة الفيديو</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_summary_on">تنطبق تغييرات الجودة على جميع الفيديوهات</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_summary_off">تنطبق تغييرات الجودة على الفيديو الحالي فقط</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_toast_title">إظهار إشعار عند تغيير جودة الفيديو</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_toast_summary_on">يتم إظهار إشعار عند تغيير جودة الفيديو الافتراضية</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_toast_summary_off">لا يتم إظهار إشعار عند تغيير جودة الفيديو الافتراضية</string>
|
||||
<string name="revanced_video_quality_default_wifi_title">جودة الفيديو الافتراضية على شبكة Wi-Fi</string>
|
||||
<string name="revanced_video_quality_default_mobile_title">جودة الفيديو الافتراضية على شبكة الجوَّال</string>
|
||||
<string name="revanced_remember_shorts_quality_last_selected_title">تذكر تغييرات جودة Shorts</string>
|
||||
@@ -1423,7 +1425,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_custom_playback_speeds_invalid">يجب أن تكون سرعات التشغيل المخصصة أقل من %s</string>
|
||||
<string name="revanced_custom_playback_speeds_parse_exception">سرعة التشغيل المخصصة غير صالحة</string>
|
||||
<string name="revanced_custom_playback_speeds_auto">تلقائي</string>
|
||||
<string name="revanced_custom_playback_speeds_reset_toast">تمت إعادة ضبط سرعة التشغيل إلى: %s</string>
|
||||
<string name="revanced_speed_tap_and_hold_title">سرعة النقر مع الاستمرار المخصصة</string>
|
||||
<string name="revanced_speed_tap_and_hold_summary">سرعة التشغيل بين 0-8</string>
|
||||
</patch>
|
||||
@@ -1431,6 +1432,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_remember_playback_speed_last_selected_title">تذكر التغيرات في سرعة التشغيل</string>
|
||||
<string name="revanced_remember_playback_speed_last_selected_summary_on">تطبيق تغييرات سرعة التشغيل على جميع الفيديوهات</string>
|
||||
<string name="revanced_remember_playback_speed_last_selected_summary_off">تطبيق تغييرات سرعة التشغيل فقط على الفيديو الحالي</string>
|
||||
<string name="revanced_remember_playback_speed_last_selected_toast_title">إظهار إشعار عند تغيير سرعة التشغيل</string>
|
||||
<string name="revanced_remember_playback_speed_last_selected_toast_summary_on">يتم إظهار إشعار عند تغيير سرعة التشغيل الافتراضية</string>
|
||||
<string name="revanced_remember_playback_speed_last_selected_toast_summary_off">لا يتم عرض إشعار عند تغيير سرعة التشغيل الافتراضية.</string>
|
||||
<string name="revanced_playback_speed_default_title">سرعة التشغيل الافتراضية</string>
|
||||
<string name="revanced_remember_playback_speed_toast">تغيير السرعة الافتراضية إلى: %s</string>
|
||||
</patch>
|
||||
|
||||
@@ -79,6 +79,7 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.buttons.action.hideButtonsPatch">
|
||||
<!-- 'Share' should be translated with the same localized wording that YouTube displays. -->
|
||||
<!-- 'Stop ads' should be translated with the same localized wording that YouTube displays. -->
|
||||
<!-- 'Report' should be translated with the same localized wording that YouTube displays.
|
||||
This button usually appears only on live streams. -->
|
||||
<!-- 'Remix' should be translated with the same localized wording that YouTube displays. -->
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user