Compare commits

..

28 Commits

Author SHA1 Message Date
semantic-release-bot
e48c152b95 chore: Release v5.29.0-dev.4 [skip ci]
# [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)) ([a678f17](a678f178e1))
2025-06-23 09:33:13 +00:00
ILoveOpenSourceApplications
a678f178e1 fix(YouTube - Hide Shorts components): Fix "Hide Use this sound button" (#5233) 2025-06-23 13:29:53 +04:00
semantic-release-bot
2d8f5641f9 chore: Release v5.29.0-dev.3 [skip ci]
# [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 ([0dbd058](0dbd058099))
2025-06-23 09:18:27 +00:00
LisoUseInAIKyrios
0dbd058099 fix(YouTube): Fix refactoring app startup exception 2025-06-23 13:15:43 +04:00
semantic-release-bot
c1a8fd0766 chore: Release v5.29.0-dev.2 [skip ci]
# [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)) ([d338989](d338989cb4))
2025-06-23 08:47:04 +00:00
hoodles
d338989cb4 feat(Crunchyroll): Add Hide ads patch (#5201) 2025-06-23 12:44:07 +04:00
github-actions[bot]
b94daacf01 chore: Sync translations (#5236) 2025-06-23 12:43:45 +04:00
semantic-release-bot
c764c4f197 chore: Release v5.29.0-dev.1 [skip ci]
# [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)) ([ccd1691](ccd169121a))

### Features

* **YouTube:** Add an option to disable toasts when changing default playback speed or quality ([#5230](https://github.com/ReVanced/revanced-patches/issues/5230)) ([6b719df](6b719dfcd7))
2025-06-23 08:24:13 +00:00
MarcaD
6b719dfcd7 feat(YouTube): Add an option to disable toasts when changing default playback speed or quality (#5230) 2025-06-23 12:20:37 +04:00
LisoUseInAIKyrios
ccd169121a fix(YouTube): Always use single threaded layout to resolve layout bugs in unpatched YouTube (#5226) 2025-06-23 12:19:07 +04:00
semantic-release-bot
dcfbd8bf93 chore: Release v5.28.1-dev.2 [skip ci]
## [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)) ([b656976](b65697603d))
2025-06-23 07:19:38 +00:00
ILoveOpenSourceApplications
b65697603d fix(YouTube - Hide ads): Hide new type of product ad in video description (#5225) 2025-06-23 11:17:08 +04:00
semantic-release-bot
25da5cca8b chore: Release v5.28.1-dev.1 [skip ci]
## [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)) ([2b62fc2](2b62fc2224))
2025-06-22 11:23:52 +00:00
MarcaD
2b62fc2224 fix: Add scrollable content to modern style settings dialogs (#5211) 2025-06-22 15:21:00 +04:00
semantic-release-bot
a9e9456b6b chore: Release v5.28.0 [skip ci]
# [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 ([1cea6bf](1cea6bfdff))
* **Messenger - Remove Meta AI:** Improve patch logic ([#5153](https://github.com/ReVanced/revanced-patches/issues/5153)) ([a8d2a1e](a8d2a1e028))
* **Pandora - Disable ads:** Support latest app target ([#5185](https://github.com/ReVanced/revanced-patches/issues/5185)) ([90868ff](90868ff025))
* **Spotify:** Fix `Hide Create button` and `Sanitize sharing links` for older but supported app targets ([#5159](https://github.com/ReVanced/revanced-patches/issues/5159)) ([5540136](55401368b8))
* **Threads - Hide ads:** Constrain patch to the last working app target ([#5189](https://github.com/ReVanced/revanced-patches/issues/5189)) ([e138501](e138501657))
* **YouTube:** Remove old app targets that are no longer supported by YouTube ([#5192](https://github.com/ReVanced/revanced-patches/issues/5192)) ([e790cfb](e790cfbf59))

### Features

* **Spotify:** Add `Change lyrics provider` patch ([#4937](https://github.com/ReVanced/revanced-patches/issues/4937)) ([7bbaca7](7bbaca77ad))
* Use modern style settings dialogs ([#5109](https://github.com/ReVanced/revanced-patches/issues/5109)) ([a426e2a](a426e2af50))
2025-06-20 08:17:57 +00:00
LisoUseInAIKyrios
b01523e97d chore: Merge branch dev to main (#5160) 2025-06-20 12:14:29 +04:00
github-actions[bot]
b8afb4e821 chore: Sync translations (#5210) 2025-06-20 12:13:39 +04:00
github-actions[bot]
0d2198faed chore: Sync translations (#5207) 2025-06-20 01:33:20 +04:00
semantic-release-bot
5c7c407b82 chore: Release v5.28.0-dev.8 [skip ci]
# [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)) ([a8d2a1e](a8d2a1e028))
2025-06-19 06:10:06 +00:00
Dawid Krajcarz
a8d2a1e028 fix(Messenger - Remove Meta AI): Improve patch logic (#5153) 2025-06-19 10:06:46 +04:00
semantic-release-bot
d31624cae8 chore: Release v5.28.0-dev.7 [skip ci]
# [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)) ([e790cfb](e790cfbf59))
2025-06-18 10:38:43 +00:00
LisoUseInAIKyrios
e790cfbf59 fix(YouTube): Remove old app targets that are no longer supported by YouTube (#5192) 2025-06-18 12:35:43 +02:00
LisoUseInAIKyrios
a54d408d3e chore: Fix string typos, fix missing long/wide returnEarly/returnLate 2025-06-18 11:06:48 +02:00
semantic-release-bot
5d3769e921 chore: Release v5.28.0-dev.6 [skip ci]
# [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)) ([e138501](e138501657))
2025-06-17 21:07:00 +00:00
LisoUseInAIKyrios
e138501657 fix(Threads - Hide ads): Constrain patch to the last working app target (#5189) 2025-06-17 23:03:35 +02:00
semantic-release-bot
a9235d6b62 chore: Release v5.28.0-dev.5 [skip ci]
# [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)

### Bug Fixes

* **Pandora - Disable ads:** Support latest app target ([#5185](https://github.com/ReVanced/revanced-patches/issues/5185)) ([90868ff](90868ff025))
2025-06-17 06:47:11 +00:00
hoodles
90868ff025 fix(Pandora - Disable ads): Support latest app target (#5185) 2025-06-17 08:44:19 +02:00
github-actions[bot]
345ec5c430 chore: Sync translations (#5188) 2025-06-17 08:43:55 +02:00
145 changed files with 1213 additions and 2319 deletions

View File

@@ -1,3 +1,96 @@
# [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)
### Bug Fixes
* **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))
# [5.28.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.28.0-dev.3...v5.28.0-dev.4) (2025-06-13) # [5.28.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.28.0-dev.3...v5.28.0-dev.4) (2025-06-13)

View File

@@ -1,15 +1,23 @@
package app.revanced.extension.messenger.metaai; package app.revanced.extension.messenger.metaai;
import java.util.*;
import app.revanced.extension.shared.Logger;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class RemoveMetaAIPatch { public class RemoveMetaAIPatch {
private static final Set<Long> loggedIDs = Collections.synchronizedSet(new HashSet<>());
public static boolean overrideBooleanFlag(long id, boolean value) { public static boolean overrideBooleanFlag(long id, boolean value) {
// This catches all flag IDs related to Meta AI. try {
// The IDs change slightly with every update, if (Long.toString(id).startsWith("REPLACED_BY_PATCH")) {
// so to work around this, IDs from different versions were compared if (loggedIDs.add(id))
// to find what they have in common, which turned out to be those first bits. Logger.printInfo(() -> "Overriding " + id + " from " + value + " to false");
// TODO: Find the specific flags that we care about and patch the code they control instead.
if ((id & 0x7FFFFFC000000000L) == 0x810A8000000000L) { return false;
return false; }
} catch (Exception ex) {
Logger.printException(() -> "overrideBooleanFlag failure", ex);
} }
return value; return value;

View File

@@ -42,6 +42,7 @@ import android.widget.EditText;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import android.widget.Toolbar; import android.widget.Toolbar;
@@ -773,16 +774,15 @@ public class Utils {
Dialog dialog = new Dialog(context); Dialog dialog = new Dialog(context);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); // Remove default title bar. 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. // Preset size constants.
final int dip4 = dipToPixels(4); final int dip4 = dipToPixels(4);
final int dip8 = dipToPixels(8); final int dip8 = dipToPixels(8);
final int dip16 = dipToPixels(16); final int dip16 = dipToPixels(16);
final int dip24 = dipToPixels(24); final int dip24 = dipToPixels(24);
// Create main layout.
LinearLayout mainLayout = new LinearLayout(context);
mainLayout.setOrientation(LinearLayout.VERTICAL);
mainLayout.setPadding(dip24, dip16, dip24, dip24); mainLayout.setPadding(dip24, dip16, dip24, dip24);
// Set rounded rectangle background. // Set rounded rectangle background.
ShapeDrawable mainBackground = new ShapeDrawable(new RoundRectShape( ShapeDrawable mainBackground = new ShapeDrawable(new RoundRectShape(
@@ -802,55 +802,71 @@ public class Utils {
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT ViewGroup.LayoutParams.WRAP_CONTENT
); );
layoutParams.setMargins(0, 0, 0, dip8); layoutParams.setMargins(0, 0, 0, dip16);
titleView.setLayoutParams(layoutParams); titleView.setLayoutParams(layoutParams);
mainLayout.addView(titleView); mainLayout.addView(titleView);
} }
// Message (if not replaced by EditText). // Create content container (message/EditText) inside a ScrollView only if message or editText is provided.
if (editText == null && message != null) { ScrollView contentScrollView = null;
TextView messageView = new TextView(context); LinearLayout contentContainer = null;
messageView.setText(message); // Supports Spanned (HTML). if (message != null || editText != null) {
messageView.setTextSize(16); contentScrollView = new ScrollView(context);
messageView.setTextColor(getAppForegroundColor()); contentScrollView.setVerticalScrollBarEnabled(false); // Disable the vertical scrollbar.
// Enable HTML link clicking if the message contains links. contentScrollView.setOverScrollMode(View.OVER_SCROLL_NEVER);
if (message instanceof Spanned) { if (editText != null) {
messageView.setMovementMethod(LinkMovementMethod.getInstance()); 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.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT 0,
1.0f // Weight to take available space.
); );
messageParams.setMargins(0, dip8, 0, dip16); contentScrollView.setLayoutParams(contentParams);
messageView.setLayoutParams(messageParams); contentContainer = new LinearLayout(context);
mainLayout.addView(messageView); contentContainer.setOrientation(LinearLayout.VERTICAL);
} contentScrollView.addView(contentContainer);
// EditText (if provided). // Message (if not replaced by EditText).
if (editText != null) { if (editText == null && message != null) {
// Remove EditText from its current parent, if any. TextView messageView = new TextView(context);
ViewGroup parent = (ViewGroup) editText.getParent(); messageView.setText(message); // Supports Spanned (HTML).
if (parent != null) { messageView.setTextSize(16);
parent.removeView(editText); 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( // EditText (if provided).
LinearLayout.LayoutParams.MATCH_PARENT, if (editText != null) {
LinearLayout.LayoutParams.WRAP_CONTENT // Remove EditText from its current parent, if any.
); ViewGroup parent = (ViewGroup) editText.getParent();
editTextParams.setMargins(0, dip8, 0, dip16); if (parent != null) {
// Prevent buttons from moving off the screen by fixing the height of the EditText. parent.removeView(editText);
final int maxHeight = (int) (context.getResources().getDisplayMetrics().heightPixels * 0.6); }
editText.setMaxHeight(maxHeight); // Style the EditText to match the dialog theme.
mainLayout.addView(editText, 1, editTextParams); 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. // Button container.
@@ -861,7 +877,7 @@ public class Utils {
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT LinearLayout.LayoutParams.WRAP_CONTENT
); );
buttonContainerParams.setMargins(0, dip8, 0, 0); buttonContainerParams.setMargins(0, dip16, 0, 0);
buttonContainer.setLayoutParams(buttonContainerParams); buttonContainer.setLayoutParams(buttonContainerParams);
// Lists to track buttons. // 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); mainLayout.addView(buttonContainer);
dialog.setContentView(mainLayout); dialog.setContentView(mainLayout);
// Set dialog window attributes. // Set dialog window attributes.
Window window = dialog.getWindow(); Window window = dialog.getWindow();
if (window != null) { if (window != null) {
setDialogWindowParameters(context, window); setDialogWindowParameters(window);
} }
return new Pair<>(dialog, mainLayout); return new Pair<>(dialog, mainLayout);
} }
public static void setDialogWindowParameters(Context context, Window window) { public static void setDialogWindowParameters(Window window) {
WindowManager.LayoutParams params = window.getAttributes(); WindowManager.LayoutParams params = window.getAttributes();
Resources resources = context.getResources(); DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
DisplayMetrics displayMetrics = resources.getDisplayMetrics();
int portraitWidth = (int) (displayMetrics.widthPixels * 0.9); 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); portraitWidth = (int) Math.min(portraitWidth, displayMetrics.heightPixels * 0.9);
} }
params.width = portraitWidth; params.width = portraitWidth;
@@ -1199,7 +1219,7 @@ public class Utils {
return darkColor == Color.BLACK return darkColor == Color.BLACK
// Lighten the background a little if using AMOLED dark theme // Lighten the background a little if using AMOLED dark theme
// as the dialogs are almost invisible. // as the dialogs are almost invisible.
? 0xFF0D0D0D ? 0xFF080808 // 3%
: darkColor; : darkColor;
} }
return getThemeLightColor(); return getThemeLightColor();

View File

@@ -129,8 +129,7 @@ abstract class Check {
ImageView iconView = new ImageView(activity); ImageView iconView = new ImageView(activity);
iconView.setImageResource(Utils.getResourceIdentifier("revanced_ic_dialog_alert", "drawable")); iconView.setImageResource(Utils.getResourceIdentifier("revanced_ic_dialog_alert", "drawable"));
iconView.setColorFilter(Utils.getAppForegroundColor(), PorterDuff.Mode.SRC_IN); iconView.setColorFilter(Utils.getAppForegroundColor(), PorterDuff.Mode.SRC_IN);
final int dip8 = dipToPixels(8); iconView.setPadding(0, 0, 0, 0);
iconView.setPadding(0, dip8, 0, dip8);
LinearLayout.LayoutParams iconParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams iconParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT LinearLayout.LayoutParams.WRAP_CONTENT

View File

@@ -24,10 +24,7 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewParent; import android.view.ViewParent;
import android.widget.Button; import android.widget.*;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.ColorInt; import androidx.annotation.ColorInt;
@@ -298,7 +295,6 @@ public class ColorPickerPreference extends EditTextPreference {
// Horizontal layout for preview and EditText. // Horizontal layout for preview and EditText.
LinearLayout inputLayout = new LinearLayout(context); LinearLayout inputLayout = new LinearLayout(context);
inputLayout.setOrientation(LinearLayout.HORIZONTAL); inputLayout.setOrientation(LinearLayout.HORIZONTAL);
inputLayout.setPadding(0, 0, 0, dipToPixels(10));
dialogColorPreview = new TextView(context); dialogColorPreview = new TextView(context);
LinearLayout.LayoutParams previewParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams previewParams = new LinearLayout.LayoutParams(
@@ -338,11 +334,23 @@ public class ColorPickerPreference extends EditTextPreference {
paddingView.setLayoutParams(params); paddingView.setLayoutParams(params);
inputLayout.addView(paddingView); inputLayout.addView(paddingView);
// Create main container for color picker and input layout. // Create content container for color picker and input layout.
LinearLayout container = new LinearLayout(context); LinearLayout contentContainer = new LinearLayout(context);
container.setOrientation(LinearLayout.VERTICAL); contentContainer.setOrientation(LinearLayout.VERTICAL);
container.addView(colorPicker); contentContainer.addView(colorPicker);
container.addView(inputLayout); 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. // Create custom dialog.
final int originalColor = currentColor & 0x00FFFFFF; final int originalColor = currentColor & 0x00FFFFFF;
@@ -391,9 +399,9 @@ public class ColorPickerPreference extends EditTextPreference {
false // Do not dismiss dialog when onNeutralClick. 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; LinearLayout dialogMainLayout = dialogPair.second;
dialogMainLayout.addView(container, 1); dialogMainLayout.addView(contentScrollView, dialogMainLayout.getChildCount() - 1);
// Set up color picker listener with debouncing. // Set up color picker listener with debouncing.
// Add listener last to prevent callbacks from set calls above. // Add listener last to prevent callbacks from set calls above.

View File

@@ -11,11 +11,7 @@ import android.util.Pair;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ArrayAdapter; import android.widget.*;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@@ -107,14 +103,16 @@ public class CustomDialogListPreference extends ListPreference {
@Override @Override
protected void showDialog(Bundle state) { protected void showDialog(Bundle state) {
Context context = getContext();
// Create ListView. // Create ListView.
ListView listView = new ListView(getContext()); ListView listView = new ListView(context);
listView.setId(android.R.id.list); listView.setId(android.R.id.list);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
// Create custom adapter for the ListView. // Create custom adapter for the ListView.
ListPreferenceArrayAdapter adapter = new ListPreferenceArrayAdapter( ListPreferenceArrayAdapter adapter = new ListPreferenceArrayAdapter(
getContext(), context,
Utils.getResourceIdentifier("revanced_custom_list_item_checked", "layout"), Utils.getResourceIdentifier("revanced_custom_list_item_checked", "layout"),
getEntries(), getEntries(),
getEntryValues(), getEntryValues(),
@@ -137,7 +135,7 @@ public class CustomDialogListPreference extends ListPreference {
// Create the custom dialog without OK button. // Create the custom dialog without OK button.
Pair<Dialog, LinearLayout> dialogPair = Utils.createCustomDialog( Pair<Dialog, LinearLayout> dialogPair = Utils.createCustomDialog(
getContext(), context,
getTitle() != null ? getTitle().toString() : "", getTitle() != null ? getTitle().toString() : "",
null, null,
null, null,
@@ -149,35 +147,13 @@ public class CustomDialogListPreference extends ListPreference {
true true
); );
Dialog dialog = dialogPair.first; // Add the ListView to the main layout.
LinearLayout mainLayout = dialogPair.second; 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 listViewParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, 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); mainLayout.addView(listView, mainLayout.getChildCount() - 1, listViewParams);
// Handle item click to select value and dismiss dialog. // Handle item click to select value and dismiss dialog.
@@ -188,10 +164,10 @@ public class CustomDialogListPreference extends ListPreference {
adapter.setSelectedValue(selectedValue); adapter.setSelectedValue(selectedValue);
adapter.notifyDataSetChanged(); adapter.notifyDataSetChanged();
} }
dialog.dismiss(); dialogPair.first.dismiss();
}); });
// Show the dialog. // Show the dialog.
dialog.show(); dialogPair.first.show();
} }
} }

View File

@@ -17,6 +17,7 @@ import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.preference.Preference; import android.preference.Preference;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View;
import android.view.Window; import android.view.Window;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
@@ -216,6 +217,8 @@ class WebViewDialog extends Dialog {
// Create WebView. // Create WebView.
WebView webView = new WebView(getContext()); WebView webView = new WebView(getContext());
webView.setVerticalScrollBarEnabled(false); // Disable the vertical scrollbar.
webView.setOverScrollMode(View.OVER_SCROLL_NEVER);
webView.getSettings().setJavaScriptEnabled(true); webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new OpenLinksExternallyWebClient()); webView.setWebViewClient(new OpenLinksExternallyWebClient());
webView.loadDataWithBaseURL(null, htmlContent, "text/html", "utf-8", null); webView.loadDataWithBaseURL(null, htmlContent, "text/html", "utf-8", null);
@@ -228,7 +231,7 @@ class WebViewDialog extends Dialog {
// Set dialog window attributes // Set dialog window attributes
Window window = getWindow(); Window window = getWindow();
if (window != null) { if (window != null) {
Utils.setDialogWindowParameters(getContext(), window); Utils.setDialogWindowParameters(window);
} }
} }

View File

@@ -7,11 +7,17 @@ public class VersionCheckPatch {
return Utils.getAppVersionName().compareTo(version) >= 0; return Utils.getAppVersionName().compareTo(version) >= 0;
} }
@Deprecated
public static final boolean IS_19_17_OR_GREATER = isVersionOrGreater("19.17.00"); 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"); 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"); 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"); 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"); 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_34_OR_GREATER = isVersionOrGreater("19.34.00");
public static final boolean IS_19_46_OR_GREATER = isVersionOrGreater("19.46.00"); public static final boolean IS_19_46_OR_GREATER = isVersionOrGreater("19.46.00");
} }

View File

@@ -121,12 +121,14 @@ public final class AdsFilter extends Filter {
playerShoppingShelf = new StringFilterGroup( playerShoppingShelf = new StringFilterGroup(
Settings.HIDE_PLAYER_STORE_SHELF, Settings.HIDE_PLAYER_STORE_SHELF,
"expandable_list.eml",
"horizontal_shelf.eml" "horizontal_shelf.eml"
); );
playerShoppingShelfBuffer = new ByteArrayFilterGroup( playerShoppingShelfBuffer = new ByteArrayFilterGroup(
null, null,
"shopping_item_card_list.eml" "shopping_link_item",
"shopping_item_card_list"
); );
channelProfile = new StringFilterGroup( channelProfile = new StringFilterGroup(

View File

@@ -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[] { private static final Filter[] filters = new Filter[] {
new DummyFilter() // Replaced by patch. new DummyFilter() // Replaced by patch.
}; };
@@ -213,9 +234,28 @@ public final class LithoFilterPatch {
return false; return false;
} }
}
/** /**
* Placeholder for actual filters. * Injection point.
*/ */
final class DummyFilter extends Filter { } 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;
}
}

View File

@@ -40,8 +40,10 @@ public final class ShortsFilter extends Filter {
private static WeakReference<PivotBar> pivotBarRef = new WeakReference<>(null); private static WeakReference<PivotBar> pivotBarRef = new WeakReference<>(null);
private final StringFilterGroup shortsCompactFeedVideoPath; private final StringFilterGroup shortsCompactFeedVideo;
private final ByteArrayFilterGroup shortsCompactFeedVideoBuffer; private final ByteArrayFilterGroup shortsCompactFeedVideoBuffer;
private final StringFilterGroup useSoundButton;
private final ByteArrayFilterGroup useSoundButtonBuffer;
private final StringFilterGroup subscribeButton; private final StringFilterGroup subscribeButton;
private final StringFilterGroup joinButton; private final StringFilterGroup joinButton;
@@ -49,11 +51,11 @@ public final class ShortsFilter extends Filter {
private final StringFilterGroup shelfHeader; private final StringFilterGroup shelfHeader;
private final StringFilterGroup suggestedAction; private final StringFilterGroup suggestedAction;
private final ByteArrayFilterGroupList suggestedActionsGroupList = new ByteArrayFilterGroupList(); private final ByteArrayFilterGroupList suggestedActionsBuffer = new ByteArrayFilterGroupList();
private final StringFilterGroup shortsActionBar; private final StringFilterGroup shortsActionBar;
private final StringFilterGroup actionButton; private final StringFilterGroup videoActionButton;
private final ByteArrayFilterGroupList videoActionButtonGroupList = new ByteArrayFilterGroupList(); private final ByteArrayFilterGroupList videoActionButtonBuffer = new ByteArrayFilterGroupList();
public ShortsFilter() { public ShortsFilter() {
// //
@@ -82,7 +84,7 @@ public final class ShortsFilter extends Filter {
// Path components. // Path components.
// //
shortsCompactFeedVideoPath = new StringFilterGroup(null, shortsCompactFeedVideo = new StringFilterGroup(null,
// Shorts that appear in the feed/search when the device is using tablet layout. // Shorts that appear in the feed/search when the device is using tablet layout.
"compact_video.eml", "compact_video.eml",
// 'video_lockup_with_attachment.eml' is shown instead of 'compact_video.eml' for some users // '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" "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, null,
// Can be simply 'button.eml', 'shorts_video_action_button.eml' or 'reel_action_button.eml' // Can be simply 'button.eml', 'shorts_video_action_button.eml' or 'reel_action_button.eml'
"button.eml" "button.eml"
@@ -186,16 +199,16 @@ public final class ShortsFilter extends Filter {
); );
addPathCallbacks( addPathCallbacks(
shortsCompactFeedVideoPath, joinButton, subscribeButton, paidPromotionButton, shortsCompactFeedVideo, joinButton, subscribeButton, paidPromotionButton,
shortsActionBar, suggestedAction, pausedOverlayButtons, channelBar, shortsActionBar, suggestedAction, pausedOverlayButtons, channelBar,
fullVideoLinkLabel, videoTitle, reelSoundMetadata, soundButton, infoPanel, fullVideoLinkLabel, videoTitle, useSoundButton, reelSoundMetadata, soundButton, infoPanel,
stickers, likeFountain, likeButton, dislikeButton stickers, likeFountain, likeButton, dislikeButton
); );
// //
// All other action buttons. // All other action buttons.
// //
videoActionButtonGroupList.addAll( videoActionButtonBuffer.addAll(
new ByteArrayFilterGroup( new ByteArrayFilterGroup(
Settings.HIDE_SHORTS_COMMENTS_BUTTON, Settings.HIDE_SHORTS_COMMENTS_BUTTON,
"reel_comment_button", "reel_comment_button",
@@ -216,7 +229,7 @@ public final class ShortsFilter extends Filter {
// //
// Suggested actions. // Suggested actions.
// //
suggestedActionsGroupList.addAll( suggestedActionsBuffer.addAll(
new ByteArrayFilterGroup( new ByteArrayFilterGroup(
Settings.HIDE_SHORTS_PREVIEW_COMMENT, Settings.HIDE_SHORTS_PREVIEW_COMMENT,
// Preview comment that can popup while a Short is playing. // Preview comment that can popup while a Short is playing.
@@ -242,10 +255,7 @@ public final class ShortsFilter extends Filter {
"yt_outline_bookmark_", "yt_outline_bookmark_",
// 'Save sound' button. It seems this has been removed and only 'Save music' is used. // 'Save sound' button. It seems this has been removed and only 'Save music' is used.
// Still hide this in case it's still present. // Still hide this in case it's still present.
"yt_outline_list_add_", "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_"
), ),
new ByteArrayFilterGroup( new ByteArrayFilterGroup(
Settings.HIDE_SHORTS_SEARCH_SUGGESTIONS, Settings.HIDE_SHORTS_SEARCH_SUGGESTIONS,
@@ -279,7 +289,7 @@ public final class ShortsFilter extends Filter {
} }
private boolean isEverySuggestedActionFilterEnabled() { private boolean isEverySuggestedActionFilterEnabled() {
for (ByteArrayFilterGroup group : suggestedActionsGroupList) { for (ByteArrayFilterGroup group : suggestedActionsBuffer) {
if (!group.isEnabled()) { if (!group.isEnabled()) {
return false; return false;
} }
@@ -297,15 +307,19 @@ public final class ShortsFilter extends Filter {
return path.startsWith(REEL_CHANNEL_BAR_PATH) || path.startsWith(REEL_METAPANEL_PATH); 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(); return shouldHideShortsFeedItems() && shortsCompactFeedVideoBuffer.check(protobufBufferArray).isFiltered();
} }
// Video action buttons (comment, share, remix) have the same path. // Video action buttons (comment, share, remix) have the same path.
// Like and dislike are separate path filters and don't require buffer searching. // Like and dislike are separate path filters and don't require buffer searching.
if (matchedGroup == shortsActionBar) { if (matchedGroup == shortsActionBar) {
return actionButton.check(path).isFiltered() return videoActionButton.check(path).isFiltered()
&& videoActionButtonGroupList.check(protobufBufferArray).isFiltered(); && videoActionButtonBuffer.check(protobufBufferArray).isFiltered();
} }
if (matchedGroup == suggestedAction) { if (matchedGroup == suggestedAction) {
@@ -316,7 +330,7 @@ public final class ShortsFilter extends Filter {
return true; return true;
} }
return suggestedActionsGroupList.check(protobufBufferArray).isFiltered(); return suggestedActionsBuffer.check(protobufBufferArray).isFiltered();
} }
return true; return true;

View File

@@ -64,10 +64,11 @@ public class RememberVideoQualityPatch {
else videoQualityWifi.save(defaultQuality); else videoQualityWifi.save(defaultQuality);
networkTypeMessage = str("revanced_remember_video_quality_wifi"); networkTypeMessage = str("revanced_remember_video_quality_wifi");
} }
Utils.showToastShort(str( if (Settings.REMEMBER_VIDEO_QUALITY_LAST_SELECTED_TOAST.get())
useShortsPreference ? "revanced_remember_video_quality_toast_shorts" : "revanced_remember_video_quality_toast", Utils.showToastShort(str(
networkTypeMessage, (defaultQuality + "p") useShortsPreference ? "revanced_remember_video_quality_toast_shorts" : "revanced_remember_video_quality_toast",
)); networkTypeMessage, (defaultQuality + "p")
));
} }
/** /**

View File

@@ -617,9 +617,9 @@ public class CustomPlaybackSpeedPatch {
* @return The rounded speed, constrained to the specified bounds. * @return The rounded speed, constrained to the specified bounds.
*/ */
private static float roundSpeedToNearestIncrement(float speed) { private static float roundSpeedToNearestIncrement(float speed) {
// Round to nearest 0.05 speed. // Round to nearest 0.05 speed. Must use double precision otherwise rounding error can occur.
final float roundedSpeed = Math.round(speed / 0.05f) * 0.05f; final double roundedSpeed = Math.round(speed / 0.05) * 0.05;
return Utils.clamp(roundedSpeed, 0.05f, PLAYBACK_SPEED_MAXIMUM); return Utils.clamp((float) roundedSpeed, 0.05f, PLAYBACK_SPEED_MAXIMUM);
} }
/** /**

View File

@@ -57,7 +57,8 @@ public final class RememberPlaybackSpeedPatch {
} }
Settings.PLAYBACK_SPEED_DEFAULT.save(finalPlaybackSpeed); 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); }, TOAST_DELAY_MILLISECONDS);
} }
} catch (Exception ex) { } catch (Exception ex) {

View File

@@ -19,6 +19,7 @@ import android.widget.SearchView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toolbar; import android.widget.Toolbar;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import java.util.ArrayList; import java.util.ArrayList;
@@ -58,11 +59,7 @@ public class SearchViewController {
GradientDrawable background = new GradientDrawable(); GradientDrawable background = new GradientDrawable();
background.setShape(GradientDrawable.RECTANGLE); background.setShape(GradientDrawable.RECTANGLE);
background.setCornerRadius(28 * context.getResources().getDisplayMetrics().density); // 28dp corner radius. background.setCornerRadius(28 * context.getResources().getDisplayMetrics().density); // 28dp corner radius.
int baseColor = Utils.getAppBackgroundColor(); background.setColor(getSearchViewBackground());
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);
return background; return background;
} }
@@ -72,10 +69,17 @@ public class SearchViewController {
private static GradientDrawable createSuggestionBackgroundDrawable(Context context) { private static GradientDrawable createSuggestionBackgroundDrawable(Context context) {
GradientDrawable background = new GradientDrawable(); GradientDrawable background = new GradientDrawable();
background.setShape(GradientDrawable.RECTANGLE); background.setShape(GradientDrawable.RECTANGLE);
background.setCornerRadius(8 * context.getResources().getDisplayMetrics().density); // 8dp corner radius. background.setColor(getSearchViewBackground());
return background; 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. * Adds search view components to the activity.
*/ */

View File

@@ -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_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 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 = 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_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 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); 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 // Speed
public static final FloatSetting SPEED_TAP_AND_HOLD = new FloatSetting("revanced_speed_tap_and_hold", 2.0f, true); 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 = 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 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 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", public static final StringSetting CUSTOM_PLAYBACK_SPEEDS = new StringSetting("revanced_custom_playback_speeds",
@@ -289,6 +293,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_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_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_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_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 HIDE_SHORTS_VIDEO_TITLE = new BooleanSetting("revanced_hide_shorts_video_title", FALSE);
public static final BooleanSetting SHORTS_AUTOPLAY = new BooleanSetting("revanced_shorts_autoplay", FALSE); public static final BooleanSetting SHORTS_AUTOPLAY = new BooleanSetting("revanced_shorts_autoplay", FALSE);

View File

@@ -18,12 +18,7 @@ import android.text.TextWatcher;
import android.util.Pair; import android.util.Pair;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.EditText; import android.widget.*;
import android.widget.GridLayout;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import androidx.annotation.ColorInt; import androidx.annotation.ColorInt;
@@ -88,8 +83,6 @@ public class SegmentCategoryListPreference extends ListPreference {
// Create the main layout for the dialog content. // Create the main layout for the dialog content.
LinearLayout contentLayout = new LinearLayout(context); LinearLayout contentLayout = new LinearLayout(context);
contentLayout.setOrientation(LinearLayout.VERTICAL); contentLayout.setOrientation(LinearLayout.VERTICAL);
final int dip10 = dipToPixels(10);
contentLayout.setPadding(0, 0, 0, dip10);
// Add behavior selection radio buttons. // Add behavior selection radio buttons.
RadioGroup radioGroup = new RadioGroup(context); RadioGroup radioGroup = new RadioGroup(context);
@@ -103,7 +96,7 @@ public class SegmentCategoryListPreference extends ListPreference {
radioGroup.addView(radioButton); radioGroup.addView(radioButton);
} }
radioGroup.setOnCheckedChangeListener((group, checkedId) -> selectedDialogEntryIndex = checkedId); radioGroup.setOnCheckedChangeListener((group, checkedId) -> selectedDialogEntryIndex = checkedId);
radioGroup.setPadding(dip10, 0, 0, 0); radioGroup.setPadding(dipToPixels(10), 0, 0, 0);
contentLayout.addView(radioGroup); contentLayout.addView(radioGroup);
// Inflate the color picker view. // Inflate the color picker view.
@@ -131,7 +124,7 @@ public class SegmentCategoryListPreference extends ListPreference {
gridParams = new GridLayout.LayoutParams(); gridParams = new GridLayout.LayoutParams();
gridParams.rowSpec = GridLayout.spec(0); // First row. gridParams.rowSpec = GridLayout.spec(0); // First row.
gridParams.columnSpec = GridLayout.spec(1); // Second column. 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 = new TextView(context);
dialogColorDotView.setLayoutParams(gridParams); dialogColorDotView.setLayoutParams(gridParams);
gridLayout.addView(dialogColorDotView); gridLayout.addView(dialogColorDotView);
@@ -250,20 +243,17 @@ public class SegmentCategoryListPreference extends ListPreference {
contentLayout.addView(gridLayout); contentLayout.addView(gridLayout);
// Set up color picker listener. // Create ScrollView to wrap the content layout.
// Do last to prevent listener callbacks while setting up view. ScrollView contentScrollView = new ScrollView(context);
dialogColorPickerView.setOnColorChangedListener(color -> { contentScrollView.setVerticalScrollBarEnabled(false); // Disable vertical scrollbar.
if (categoryColor == color) { contentScrollView.setOverScrollMode(View.OVER_SCROLL_NEVER); // Disable overscroll effect.
return; LinearLayout.LayoutParams scrollViewParams = new LinearLayout.LayoutParams(
} LinearLayout.LayoutParams.MATCH_PARENT,
categoryColor = color; 0,
String hexColor = getColorString(color); 1.0f
Logger.printDebug(() -> "onColorChanged: " + hexColor); );
contentScrollView.setLayoutParams(scrollViewParams);
updateCategoryColorDot(); contentScrollView.addView(contentLayout);
dialogColorEditText.setText(hexColor);
dialogColorEditText.setSelection(hexColor.length());
});
// Create the custom dialog. // Create the custom dialog.
Pair<Dialog, LinearLayout> dialogPair = Utils.createCustomDialog( Pair<Dialog, LinearLayout> dialogPair = Utils.createCustomDialog(
@@ -309,13 +299,27 @@ public class SegmentCategoryListPreference extends ListPreference {
false // Do not dismiss dialog on Neutral button click. 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; LinearLayout dialogMainLayout = dialogPair.second;
dialogMainLayout.addView(contentScrollView, dialogMainLayout.getChildCount() - 1);
// Add the custom content to the dialog's main layout. // Set up color picker listener.
dialogMainLayout.addView(contentLayout, 1); // Add after title, before buttons. // 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. // Show the dialog.
dialog = dialogPair.first;
dialog.show(); dialog.show();
} catch (Exception ex) { } catch (Exception ex) {
Logger.printException(() -> "showDialog failure", ex); Logger.printException(() -> "showDialog failure", ex);

View File

@@ -42,7 +42,6 @@ public class PlaybackSpeedDialogButton {
: Settings.PLAYBACK_SPEED_DEFAULT.get(); : Settings.PLAYBACK_SPEED_DEFAULT.get();
VideoInformation.overridePlaybackSpeed(speed); VideoInformation.overridePlaybackSpeed(speed);
showToastShort(str("revanced_custom_playback_speeds_reset_toast", (speed + "x")));
} catch (Exception ex) { } catch (Exception ex) {
Logger.printException(() -> "speed button reset failure", ex); Logger.printException(() -> "speed button reset failure", ex);
} }

View File

@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
org.gradle.parallel = true org.gradle.parallel = true
android.useAndroidX = true android.useAndroidX = true
kotlin.code.style = official kotlin.code.style = official
version = 5.28.0-dev.4 version = 5.29.0-dev.4

View File

@@ -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 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 final class app/revanced/patches/duolingo/ad/DisableAdsPatchKt {
public static final fun getDisableAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; 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 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 final class app/revanced/patches/ticktick/misc/themeunlock/UnlockThemePatchKt {
public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
} }

View File

@@ -0,0 +1,7 @@
package app.revanced.patches.crunchyroll.ads
import app.revanced.patcher.fingerprint
internal val videoUrlReadyToStringFingerprint = fingerprint {
strings("VideoUrlReady(url=", ", enableAds=")
}

View File

@@ -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
""")
}
}

View File

@@ -1,9 +1,16 @@
package app.revanced.patches.instagram.ads package app.revanced.patches.instagram.ads
import app.revanced.patcher.patch.bytecodePatch 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") @Suppress("unused")
val hideAdsPatch = bytecodePatch { val hideAdsPatch = bytecodePatch(
dependsOn(app.revanced.patches.meta.ads.hideAdsPatch) name = "Hide ads",
) {
compatibleWith("com.instagram.android")
execute {
adInjectorFingerprint.method.returnEarly(false)
}
} }

View File

@@ -11,3 +11,15 @@ internal val getMobileConfigBoolFingerprint = fingerprint {
classDef.interfaces.contains("Lcom/facebook/mobileconfig/factory/MobileConfigUnsafeContext;") 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
}
}

View File

@@ -2,11 +2,14 @@ package app.revanced.patches.messenger.metaai
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.messenger.misc.extension.sharedExtensionPatch 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.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") @Suppress("unused")
val removeMetaAIPatch = bytecodePatch( val removeMetaAIPatch = bytecodePatch(
@@ -25,10 +28,25 @@ val removeMetaAIPatch = bytecodePatch(
addInstructions( addInstructions(
returnIndex, 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 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"
"""
)
}
} }
} }

View File

@@ -2,4 +2,4 @@ package app.revanced.patches.messenger.misc.extension
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
val sharedExtensionPatch = sharedExtensionPatch("messenger", mainActivityOnCreateHook) val sharedExtensionPatch = sharedExtensionPatch("messenger", messengerApplicationOnCreateHook)

View File

@@ -2,6 +2,8 @@ package app.revanced.patches.messenger.misc.extension
import app.revanced.patches.shared.misc.extension.extensionHook import app.revanced.patches.shared.misc.extension.extensionHook
internal val mainActivityOnCreateHook = extensionHook { internal val messengerApplicationOnCreateHook = extensionHook {
strings("MainActivity_onCreate_begin") custom { method, classDef ->
method.name == "onCreate" && classDef.endsWith("/MessengerApplication;")
}
} }

View File

@@ -3,18 +3,9 @@ package app.revanced.patches.meta.ads
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.util.returnEarly import app.revanced.util.returnEarly
@Deprecated("Instead use the Instagram or Threads specific hide ads patch")
@Suppress("unused") @Suppress("unused")
val hideAdsPatch = bytecodePatch( val hideAdsPatch = bytecodePatch {
name = "Hide ads",
) {
/**
* Patch is identical for both Instagram and Threads app.
*/
compatibleWith(
"com.instagram.android",
"com.instagram.barcelona",
)
execute { execute {
adInjectorFingerprint.method.returnEarly(false) adInjectorFingerprint.method.returnEarly(false)
} }

View File

@@ -1,12 +1,7 @@
package app.revanced.patches.pandora.ads package app.revanced.patches.pandora.ads
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.pandora.shared.constructUserDataFingerprint import app.revanced.util.returnEarly
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Suppress("unused") @Suppress("unused")
val disableAudioAdsPatch = bytecodePatch( val disableAudioAdsPatch = bytecodePatch(
@@ -15,16 +10,7 @@ val disableAudioAdsPatch = bytecodePatch(
compatibleWith("com.pandora.android") compatibleWith("com.pandora.android")
execute { execute {
constructUserDataFingerprint.method.apply { getIsAdSupportedFingerprint.method.returnEarly(false)
// First match is "hasAudioAds". requestAudioAdFingerprint.method.returnEarly()
val hasAudioAdsStringIndex = constructUserDataFingerprint.stringMatches!!.first().index
val moveResultIndex = indexOfFirstInstructionOrThrow(hasAudioAdsStringIndex, Opcode.MOVE_RESULT)
val hasAudioAdsRegister = getInstruction<OneRegisterInstruction>(moveResultIndex).registerA
addInstruction(
moveResultIndex + 1,
"const/4 v$hasAudioAdsRegister, 0"
)
}
} }
} }

View File

@@ -0,0 +1,15 @@
package app.revanced.patches.pandora.ads
import app.revanced.patcher.fingerprint
internal val getIsAdSupportedFingerprint = fingerprint {
custom { method, classDef ->
method.name == "getIsAdSupported" && classDef.endsWith("UserData;")
}
}
internal val requestAudioAdFingerprint = fingerprint {
custom { method, classDef ->
method.name == "requestAudioAdFromAdSDK" && classDef.endsWith("ContentServiceOpsImpl;")
}
}

View File

@@ -1,12 +1,7 @@
package app.revanced.patches.pandora.misc package app.revanced.patches.pandora.misc
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.pandora.shared.constructUserDataFingerprint import app.revanced.util.returnEarly
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Suppress("unused") @Suppress("unused")
val enableUnlimitedSkipsPatch = bytecodePatch( val enableUnlimitedSkipsPatch = bytecodePatch(
@@ -15,17 +10,6 @@ val enableUnlimitedSkipsPatch = bytecodePatch(
compatibleWith("com.pandora.android") compatibleWith("com.pandora.android")
execute { execute {
constructUserDataFingerprint.method.apply { skipLimitBehaviorFingerprint.method.returnEarly("unlimited")
// Last match is "skipLimitBehavior".
val skipLimitBehaviorStringIndex = constructUserDataFingerprint.stringMatches!!.last().index
val moveResultObjectIndex =
indexOfFirstInstructionOrThrow(skipLimitBehaviorStringIndex, Opcode.MOVE_RESULT_OBJECT)
val skipLimitBehaviorRegister = getInstruction<OneRegisterInstruction>(moveResultObjectIndex).registerA
addInstruction(
moveResultObjectIndex + 1,
"const-string v$skipLimitBehaviorRegister, \"unlimited\""
)
}
} }
} }

View File

@@ -0,0 +1,9 @@
package app.revanced.patches.pandora.misc
import app.revanced.patcher.fingerprint
internal val skipLimitBehaviorFingerprint = fingerprint {
custom { method, classDef ->
method.name == "getSkipLimitBehavior" && classDef.endsWith("UserData;")
}
}

View File

@@ -1,7 +0,0 @@
package app.revanced.patches.pandora.shared
import app.revanced.patcher.fingerprint
internal val constructUserDataFingerprint = fingerprint {
strings("hasAudioAds", "skipLimitBehavior")
}

View File

@@ -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)
}
}

View File

@@ -77,8 +77,6 @@ val hideAdsPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -25,8 +25,6 @@ val hideGetPremiumPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -23,8 +23,6 @@ val videoAdsPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -53,8 +53,6 @@ val copyVideoUrlPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -24,8 +24,6 @@ val removeViewerDiscretionDialogPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -72,8 +72,6 @@ val downloadsPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -20,8 +20,6 @@ val seekbarPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -18,8 +18,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/SeekbarThumbnailsPatch;" "Lapp/revanced/extension/youtube/patches/SeekbarThumbnailsPatch;"
val seekbarThumbnailsPatch = bytecodePatch( val seekbarThumbnailsPatch = bytecodePatch(
description = "Adds an option to use high quality fullscreen seekbar thumbnails. " + description = "Adds an option to use high quality fullscreen seekbar thumbnails."
"Patching 19.16.39 adds an option to restore old seekbar thumbnails.",
) { ) {
dependsOn( dependsOn(
sharedExtensionPatch, sharedExtensionPatch,

View File

@@ -88,8 +88,6 @@ val swipeControlsPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -24,8 +24,6 @@ val autoCaptionsPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -43,8 +43,6 @@ val customBrandingPatch = resourcePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -41,8 +41,6 @@ val changeHeaderPatch = resourcePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -22,8 +22,6 @@ val hideButtonsPatch = resourcePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -40,8 +40,6 @@ val navigationButtonsPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -58,8 +58,6 @@ val hidePlayerOverlayButtonsPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -33,8 +33,6 @@ val changeFormFactorPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -59,8 +59,6 @@ val hideEndscreenCardsPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -31,8 +31,6 @@ val hideEndScreenSuggestedVideoPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -29,8 +29,6 @@ val disableFullscreenAmbientModePatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -125,8 +125,6 @@ val hideLayoutComponentsPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -57,8 +57,6 @@ val hideInfoCardsPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -24,8 +24,6 @@ val hidePlayerFlyoutMenuPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -48,8 +48,6 @@ val hideRelatedVideoOverlayPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -29,8 +29,6 @@ val disableRollingNumberAnimationPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -94,6 +94,7 @@ private val hideShortsComponentsResourcePatch = resourcePatch {
// Suggested actions. // Suggested actions.
SwitchPreference("revanced_hide_shorts_preview_comment"), SwitchPreference("revanced_hide_shorts_preview_comment"),
SwitchPreference("revanced_hide_shorts_save_sound_button"), 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_use_template_button"),
SwitchPreference("revanced_hide_shorts_upcoming_button"), SwitchPreference("revanced_hide_shorts_upcoming_button"),
SwitchPreference("revanced_hide_shorts_green_screen_button"), SwitchPreference("revanced_hide_shorts_green_screen_button"),
@@ -170,8 +171,6 @@ val hideShortsComponentsPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -21,8 +21,6 @@ val hideTimestampPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -153,22 +153,6 @@ val miniplayerPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "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.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -21,8 +21,6 @@ val playerPopupPanelsPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -21,8 +21,6 @@ internal val exitFullscreenPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -52,8 +52,6 @@ val customPlayerOverlayOpacityPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -61,8 +61,6 @@ val returnYouTubeDislikePatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -66,8 +66,6 @@ val wideSearchbarPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -44,8 +44,6 @@ val shortsAutoplayPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -64,8 +64,6 @@ val openShortsInRegularPlayerPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -126,8 +126,6 @@ val sponsorBlockPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -58,8 +58,6 @@ val spoofAppVersionPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -32,8 +32,6 @@ val changeStartPagePatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -34,8 +34,6 @@ val disableResumingShortsOnStartupPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -204,8 +204,6 @@ val themePatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -33,8 +33,6 @@ val alternativeThumbnailsPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -27,8 +27,6 @@ val bypassImageRegionRestrictionsPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -23,8 +23,6 @@ val announcementsPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -24,8 +24,6 @@ val autoRepeatPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -51,8 +51,6 @@ val backgroundPlaybackPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -35,8 +35,6 @@ val enableDebuggingPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -24,8 +24,6 @@ val spoofDeviceDimensionsPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -21,8 +21,6 @@ val checkWatchHistoryDomainNameResolutionPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -35,8 +35,6 @@ val gmsCoreSupportPatch = gmsCoreSupportPatch(
compatibleWith( compatibleWith(
YOUTUBE_PACKAGE_NAME( YOUTUBE_PACKAGE_NAME(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -26,8 +26,6 @@ val disableHapticFeedbackPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -32,8 +32,6 @@ val bypassURLRedirectsPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -41,8 +41,6 @@ val openLinksExternallyPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -1,6 +1,7 @@
package app.revanced.patches.youtube.misc.litho.filter package app.revanced.patches.youtube.misc.litho.filter
import app.revanced.patcher.fingerprint import app.revanced.patcher.fingerprint
import app.revanced.util.containsLiteralInstruction
import app.revanced.util.literal import app.revanced.util.literal
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
@@ -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 { internal val lithoComponentNameUpbFeatureFlagFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("Z") returns("Z")

View File

@@ -209,6 +209,22 @@ val lithoFilterPatch = bytecodePatch(
// endregion // 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. // 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 // Turn off native code that handles litho component names. If this feature is on then nearly

View File

@@ -5,29 +5,37 @@ package app.revanced.patches.youtube.misc.playservice
import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.patch.resourcePatch
import app.revanced.util.findElementByAttributeValueOrThrow 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 var is_19_03_or_greater = false
private set 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 var is_19_04_or_greater = false
private set 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 var is_19_16_or_greater = false
private set private set
@Deprecated("19.34.42 is the lowest supported version")
var is_19_17_or_greater = false var is_19_17_or_greater = false
private set private set
@Deprecated("19.34.42 is the lowest supported version")
var is_19_18_or_greater = false var is_19_18_or_greater = false
private set private set
@Deprecated("19.34.42 is the lowest supported version")
var is_19_23_or_greater = false var is_19_23_or_greater = false
private set private set
@Deprecated("19.34.42 is the lowest supported version")
var is_19_25_or_greater = false var is_19_25_or_greater = false
private set private set
@Deprecated("19.34.42 is the lowest supported version")
var is_19_26_or_greater = false var is_19_26_or_greater = false
private set private set
@Deprecated("19.34.42 is the lowest supported version")
var is_19_29_or_greater = false var is_19_29_or_greater = false
private set private set
@Deprecated("19.34.42 is the lowest supported version")
var is_19_32_or_greater = false var is_19_32_or_greater = false
private set private set
@Deprecated("19.34.42 is the lowest supported version")
var is_19_33_or_greater = false var is_19_33_or_greater = false
private set private set
var is_19_34_or_greater = false var is_19_34_or_greater = false

View File

@@ -30,8 +30,6 @@ val removeTrackingQueryParameterPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -17,8 +17,6 @@ import app.revanced.patches.youtube.misc.settings.settingsPatch
val spoofVideoStreamsPatch = spoofVideoStreamsPatch({ val spoofVideoStreamsPatch = spoofVideoStreamsPatch({
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -41,8 +41,6 @@ val forceOriginalAudioPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -28,8 +28,6 @@ val disableHdrPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -57,7 +57,8 @@ val rememberVideoQualityPatch = bytecodePatch {
entriesKey = "revanced_shorts_quality_default_entries", entriesKey = "revanced_shorts_quality_default_entries",
entryValuesKey = "revanced_shorts_quality_default_entry_values" 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")
)) ))
/* /*

View File

@@ -23,8 +23,6 @@ val videoQualityPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -28,8 +28,6 @@ val playbackSpeedPatch = bytecodePatch(
compatibleWith( compatibleWith(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.47.53", "19.47.53",

View File

@@ -39,7 +39,8 @@ internal val rememberPlaybackSpeedPatch = bytecodePatch {
entryValuesKey = null, entryValuesKey = null,
tag = "app.revanced.extension.youtube.settings.preference.CustomVideoSpeedListPreference" 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")
) )
) )

View File

@@ -10,6 +10,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass 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.MutableField.Companion.toMutable
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patcher.util.smali.ExternalLabel
@@ -1011,8 +1012,8 @@ private fun MutableMethod.overrideReturnValue(value: String, returnLate: Boolean
} }
if (returnLate) { if (returnLate) {
findInstructionIndicesReversed { findInstructionIndicesReversedOrThrow {
opcode == RETURN || opcode == RETURN_OBJECT opcode == RETURN || opcode == RETURN_WIDE || opcode == RETURN_OBJECT
}.forEach { index -> }.forEach { index ->
addInstructionsAtControlFlowLabel(index, instructions) 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( internal fun BytecodePatchContext.addStaticFieldToExtension(
className: String, className: String,
methodName: String, methodName: String,

View File

@@ -33,11 +33,12 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="misc.settings.settingsResourcePatch"> <patch id="misc.settings.settingsResourcePatch">
<string name="revanced_settings_submenu_title">الإعدادات</string> <string name="revanced_settings_submenu_title">الإعدادات</string>
<string name="revanced_settings_confirm_user_dialog_title">هل ترغب في المتابعة؟</string> <string name="revanced_settings_confirm_user_dialog_title">هل أنت متأكد أنك تريد المتابعة؟</string>
<string name="revanced_settings_reset">إعادة التعيين</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_color_invalid">لون غير صالح</string>
<string name="revanced_settings_restart_title">تحديث وإعادة التشغيل</string> <string name="revanced_settings_restart_title">إعادة التشغيل مطلوبة</string>
<string name="revanced_settings_restart_dialog_message">أعد تشغيل التطبيق لكي يسري هذا التغيير.</string>
<string name="revanced_settings_restart">إعادة التشغيل</string> <string name="revanced_settings_restart">إعادة التشغيل</string>
<string name="revanced_settings_import">استيراد</string> <string name="revanced_settings_import">استيراد</string>
<string name="revanced_settings_import_copy">نسخ</string> <string name="revanced_settings_import_copy">نسخ</string>
@@ -920,8 +921,6 @@ Second \"item\" text"</string>
<string name="revanced_seekbar_thumbnails_high_quality_title">تمكين المصغرات عالية الجودة</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_on">مصغرات شريط التقدم عالية الجودة</string>
<string name="revanced_seekbar_thumbnails_high_quality_summary_off">مصغرات شريط التقدم متوسطة الجودة</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">"سيؤدي هذا أيضا إلى استعادة المصغرات على البث المباشر الذي لا يحتوي على مصغرات شريط التقدم. <string name="revanced_seekbar_thumbnails_high_quality_dialog_message">"سيؤدي هذا أيضا إلى استعادة المصغرات على البث المباشر الذي لا يحتوي على مصغرات شريط التقدم.
مصغرات شريط التقدم سوف تستخدم نفس جودة الفيديو الحالي. مصغرات شريط التقدم سوف تستخدم نفس جودة الفيديو الحالي.
@@ -1008,7 +1007,7 @@ Second \"item\" text"</string>
<string name="revanced_sb_segments_highlight_sum">الجزء من الفيديو الذي يبحث عنه معظم الناس</string> <string name="revanced_sb_segments_highlight_sum">الجزء من الفيديو الذي يبحث عنه معظم الناس</string>
<string name="revanced_sb_segments_intro">المقدمة/فاصل</string> <string name="revanced_sb_segments_intro">المقدمة/فاصل</string>
<string name="revanced_sb_segments_intro_sum">فاصل زمني بدون محتوى فعلي. قد يكون توقفًا مؤقتًا، أو إطارًا ثابتًا، أو رسومًا متحركة متكررة. لا يتضمن انتقالات تحتوي على معلومات</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_outro_sum">تتر النهاية أو عندما تظهر بطاقات نهاية YouTube، نهايات غير منطوقة. ليس للاستنتاجات مع المعلومات</string>
<string name="revanced_sb_segments_preview">معاينة/موجز/ربط</string> <string name="revanced_sb_segments_preview">معاينة/موجز/ربط</string>
<string name="revanced_sb_segments_preview_sum">مجموعة من المقاطع التي توضح ما هو قادم أو ما حدث في الفيديو أو في مقاطع فيديو أخرى من السلسلة، حيث تتكرر جميع المعلومات في مكان آخر</string> <string name="revanced_sb_segments_preview_sum">مجموعة من المقاطع التي توضح ما هو قادم أو ما حدث في الفيديو أو في مقاطع فيديو أخرى من السلسلة، حيث تتكرر جميع المعلومات في مكان آخر</string>
@@ -1130,7 +1129,6 @@ Second \"item\" text"</string>
<string name="revanced_change_form_factor_entry_1">الافتراضي</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_2">الجوّال</string>
<string name="revanced_change_form_factor_entry_3">الجهاز اللوحي</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">"التغييرات تشمل: <string name="revanced_change_form_factor_user_dialog_message">"التغييرات تشمل:
تصميم الجهاز اللوحي تصميم الجهاز اللوحي
@@ -1240,11 +1238,6 @@ Second \"item\" text"</string>
<string name="revanced_miniplayer_hide_overlay_buttons_title">إخفاء أزرار الواجهة</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_on">تم إخفاء أزرار الواجهة</string>
<string name="revanced_miniplayer_hide_overlay_buttons_summary_off">يتم عرض أزرار الواجهة</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_title">إخفاء النصوص الفرعية</string>
<string name="revanced_miniplayer_hide_subtext_summary_on">تم إخفاء النصوص الفرعية</string> <string name="revanced_miniplayer_hide_subtext_summary_on">تم إخفاء النصوص الفرعية</string>
<string name="revanced_miniplayer_hide_subtext_summary_off">يتم عرض النصوص الفرعية</string> <string name="revanced_miniplayer_hide_subtext_summary_off">يتم عرض النصوص الفرعية</string>
@@ -1302,8 +1295,8 @@ Second \"item\" text"</string>
<string name="revanced_alt_thumbnail_dearrow_connection_toast_title">عرض ملاحظة إذا كان API غير متاح</string> <string name="revanced_alt_thumbnail_dearrow_connection_toast_title">عرض ملاحظة إذا كان API غير متاح</string>
<string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_on">يتم عرض ملاحظة إذا كان DeArrow غير متوفر</string> <string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_on">يتم عرض ملاحظة إذا كان DeArrow غير متوفر</string>
<string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_off">لا يتم عرض ملاحظة إذا كان DeArrow غير متوفر</string> <string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_off">لا يتم عرض ملاحظة إذا كان DeArrow غير متوفر</string>
<string name="revanced_alt_thumbnail_dearrow_api_url_title">DeArrow API endpoint</string> <string name="revanced_alt_thumbnail_dearrow_api_url_title">نقطة نهاية واجهة برمجة تطبيقات DeArrow</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_summary">عنوان URL لنقطة نهاية ذاكرة التخزين المؤقت للصور المصغرة لـ DeArrow</string>
<string name="revanced_alt_thumbnail_stills_about_title">لقطات الفيديو الثابتة</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_about_summary">يتم التقاط اللقطات الثابتة من بداية/وسط/نهاية كل فيديو. هذه الصور مدمجة في YouTube ولا يتم استخدام أي واجهة برمجة تطبيقات خارجية</string>
<string name="revanced_alt_thumbnail_stills_fast_title">استخدم اللقطات الثابتة السريعة</string> <string name="revanced_alt_thumbnail_stills_fast_title">استخدم اللقطات الثابتة السريعة</string>
@@ -1396,6 +1389,9 @@ Second \"item\" text"</string>
<string name="revanced_remember_video_quality_last_selected_title">تذكر تغييرات جودة الفيديو</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_on">تنطبق تغييرات الجودة على جميع الفيديوهات</string>
<string name="revanced_remember_video_quality_last_selected_summary_off">تنطبق تغييرات الجودة على الفيديو الحالي فقط</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_wifi_title">جودة الفيديو الافتراضية على شبكة Wi-Fi</string>
<string name="revanced_video_quality_default_mobile_title">جودة الفيديو الافتراضية على شبكة الجوَّال</string> <string name="revanced_video_quality_default_mobile_title">جودة الفيديو الافتراضية على شبكة الجوَّال</string>
<string name="revanced_remember_shorts_quality_last_selected_title">تذكر تغييرات جودة Shorts</string> <string name="revanced_remember_shorts_quality_last_selected_title">تذكر تغييرات جودة Shorts</string>
@@ -1422,7 +1418,6 @@ Second \"item\" text"</string>
<string name="revanced_custom_playback_speeds_invalid">يجب أن تكون سرعات التشغيل المخصصة أقل من %s</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_parse_exception">سرعة التشغيل المخصصة غير صالحة</string>
<string name="revanced_custom_playback_speeds_auto">تلقائي</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_title">سرعة النقر مع الاستمرار المخصصة</string>
<string name="revanced_speed_tap_and_hold_summary">سرعة التشغيل بين 0-8</string> <string name="revanced_speed_tap_and_hold_summary">سرعة التشغيل بين 0-8</string>
</patch> </patch>
@@ -1430,6 +1425,9 @@ Second \"item\" text"</string>
<string name="revanced_remember_playback_speed_last_selected_title">تذكر التغيرات في سرعة التشغيل</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_on">تطبيق تغييرات سرعة التشغيل على جميع الفيديوهات</string>
<string name="revanced_remember_playback_speed_last_selected_summary_off">تطبيق تغييرات سرعة التشغيل فقط على الفيديو الحالي</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_playback_speed_default_title">سرعة التشغيل الافتراضية</string>
<string name="revanced_remember_playback_speed_toast">تغيير السرعة الافتراضية إلى: %s</string> <string name="revanced_remember_playback_speed_toast">تغيير السرعة الافتراضية إلى: %s</string>
</patch> </patch>

View File

@@ -33,11 +33,12 @@ Second \"item\" text"</string>
</patch> </patch>
<patch id="misc.settings.settingsResourcePatch"> <patch id="misc.settings.settingsResourcePatch">
<string name="revanced_settings_submenu_title">Tənzimləmələr</string> <string name="revanced_settings_submenu_title">Tənzimləmələr</string>
<string name="revanced_settings_confirm_user_dialog_title">Davam etmək istəyirsiniz?</string> <string name="revanced_settings_confirm_user_dialog_title">Davam etmək istədiyinizə əminsiniz?</string>
<string name="revanced_settings_reset">Sıfırla</string> <string name="revanced_settings_reset">Sıfırla</string>
<string name="revanced_settings_reset_color">Rəngi sıfırla</string> <string name="revanced_settings_reset_color">Rəngi sıfırla</string>
<string name="revanced_settings_color_invalid">Yanlış rəng</string> <string name="revanced_settings_color_invalid">Yanlış rəng</string>
<string name="revanced_settings_restart_title">Yenilə və yenidən başlat</string> <string name="revanced_settings_restart_title">Yenidən başlatma tələb olunur</string>
<string name="revanced_settings_restart_dialog_message">Bu dəyişikliyin təsir etməsi üçün tətbiqi yenidən başladın.</string>
<string name="revanced_settings_restart">Yenidən başlat</string> <string name="revanced_settings_restart">Yenidən başlat</string>
<string name="revanced_settings_import">İdxal et</string> <string name="revanced_settings_import">İdxal et</string>
<string name="revanced_settings_import_copy">Köçür</string> <string name="revanced_settings_import_copy">Köçür</string>
@@ -919,8 +920,6 @@ Məhdudiyyət: Bəyənməmələr gizli rejimdə görünməyə bilər"</string>
<string name="revanced_seekbar_thumbnails_high_quality_title">Yüksək keyfiyyətli miniatürləri aktivləşdir</string> <string name="revanced_seekbar_thumbnails_high_quality_title">Yüksək keyfiyyətli miniatürləri aktivləşdir</string>
<string name="revanced_seekbar_thumbnails_high_quality_summary_on">İrəliləyiş cizgisi miniatürləri yüksək keyfiyyətlidir</string> <string name="revanced_seekbar_thumbnails_high_quality_summary_on">İrəliləyiş cizgisi miniatürləri yüksək keyfiyyətlidir</string>
<string name="revanced_seekbar_thumbnails_high_quality_summary_off">İrəliləyiş cizgisi miniatürləri orta keyfiyyətlidir</string> <string name="revanced_seekbar_thumbnails_high_quality_summary_off">İrəliləyiş cizgisi miniatürləri orta keyfiyyətlidir</string>
<string name="revanced_seekbar_thumbnails_high_quality_legacy_summary_on">Tam ekran irəliləyiş cizgisi miniatürü yüksək keyfiyyətlidir</string>
<string name="revanced_seekbar_thumbnails_high_quality_legacy_summary_off">Tam ekran irəliləyiş cizgisi miniatürləri orta keyfiyyətlidir</string>
<string name="revanced_seekbar_thumbnails_high_quality_dialog_message">"Bu, həmçinin irəliləyiş cizgisi miniatürləri olmayan canlı yayımlarda miniatürləri bərpa edəcək. <string name="revanced_seekbar_thumbnails_high_quality_dialog_message">"Bu, həmçinin irəliləyiş cizgisi miniatürləri olmayan canlı yayımlarda miniatürləri bərpa edəcək.
İrəliləyiş cizgisi miniatürləri cari video kimi eyni keyfiyyəti işlədəcək. İrəliləyiş cizgisi miniatürləri cari video kimi eyni keyfiyyəti işlədəcək.
@@ -1007,7 +1006,7 @@ Sizin istifadəçi Id-niz parol kimidir və heç vaxt paylaşmaq olmaz.
<string name="revanced_sb_segments_highlight_sum">Əksər insanların axtardığı video bölümü</string> <string name="revanced_sb_segments_highlight_sum">Əksər insanların axtardığı video bölümü</string>
<string name="revanced_sb_segments_intro">Fasilə/Giriş Animasiyası</string> <string name="revanced_sb_segments_intro">Fasilə/Giriş Animasiyası</string>
<string name="revanced_sb_segments_intro_sum">Həqiqi məzmunu olmayan aralıq. Fasilə, statik kadr və ya təkrarlanan animasiya ola bilər. Məlumat ehtiva edən keçidlər daxil deyil</string> <string name="revanced_sb_segments_intro_sum">Həqiqi məzmunu olmayan aralıq. Fasilə, statik kadr və ya təkrarlanan animasiya ola bilər. Məlumat ehtiva edən keçidlər daxil deyil</string>
<string name="revanced_sb_segments_outro">Son kartlar/Zaminlər</string> <string name="revanced_sb_segments_outro">Son kartlar / Zaminlər</string>
<string name="revanced_sb_segments_outro_sum">Zaminlər və ya YouTube bitiş kartları görünəndə. Məlumat daxil olan nəticələr üçün deyil</string> <string name="revanced_sb_segments_outro_sum">Zaminlər və ya YouTube bitiş kartları görünəndə. Məlumat daxil olan nəticələr üçün deyil</string>
<string name="revanced_sb_segments_preview">Önizləmə/Anons/Qısa</string> <string name="revanced_sb_segments_preview">Önizləmə/Anons/Qısa</string>
<string name="revanced_sb_segments_preview_sum">Videoda və ya seriyanın digər videolarında nə gözlənildiyini və ya baş verdiyini göstərən, bütün məlumatların başqa yerdə təkrarlandığı bölüm toplusu</string> <string name="revanced_sb_segments_preview_sum">Videoda və ya seriyanın digər videolarında nə gözlənildiyini və ya baş verdiyini göstərən, bütün məlumatların başqa yerdə təkrarlandığı bölüm toplusu</string>
@@ -1239,11 +1238,6 @@ Kiçik oynadıcı ekrandan sola və ya sağa sürüklənə bilər"</string>
<string name="revanced_miniplayer_hide_overlay_buttons_title">Örtük düymələrini gizlət</string> <string name="revanced_miniplayer_hide_overlay_buttons_title">Örtük düymələrini gizlət</string>
<string name="revanced_miniplayer_hide_overlay_buttons_summary_on">Örtük düymələri gizlidir</string> <string name="revanced_miniplayer_hide_overlay_buttons_summary_on">Örtük düymələri gizlidir</string>
<string name="revanced_miniplayer_hide_overlay_buttons_summary_off">Örtük düymələri görünür</string> <string name="revanced_miniplayer_hide_overlay_buttons_summary_off">Örtük düymələri görünür</string>
<string name="revanced_miniplayer_hide_overlay_buttons_legacy_title">Genişləndir və bağla düymələrini gizlət</string>
<string name="revanced_miniplayer_hide_overlay_buttons_legacy_summary_on">"Düymələr gizlidir
Genişləndirmək və ya bağlamaq üçün sürüşdür"</string>
<string name="revanced_miniplayer_hide_overlay_buttons_legacy_summary_off">Genişləndir və bağla düymələri göstərilir</string>
<string name="revanced_miniplayer_hide_subtext_title">Alt mətnləri gizlət</string> <string name="revanced_miniplayer_hide_subtext_title">Alt mətnləri gizlət</string>
<string name="revanced_miniplayer_hide_subtext_summary_on">Alt mətnlər gizlədilir</string> <string name="revanced_miniplayer_hide_subtext_summary_on">Alt mətnlər gizlədilir</string>
<string name="revanced_miniplayer_hide_subtext_summary_off">Alt mətnlər göstərilir</string> <string name="revanced_miniplayer_hide_subtext_summary_off">Alt mətnlər göstərilir</string>
@@ -1421,7 +1415,6 @@ Bunu aktivləşdirmə daha yüksək video keyfiyyətləri əngəlin silə bilər
<string name="revanced_custom_playback_speeds_invalid">Fərdi sürətlər %s dəyərindən az olmalıdır</string> <string name="revanced_custom_playback_speeds_invalid">Fərdi sürətlər %s dəyərindən az olmalıdır</string>
<string name="revanced_custom_playback_speeds_parse_exception">Fərdi oynatma sürətləri etibarsızdır</string> <string name="revanced_custom_playback_speeds_parse_exception">Fərdi oynatma sürətləri etibarsızdır</string>
<string name="revanced_custom_playback_speeds_auto">Avtomatik</string> <string name="revanced_custom_playback_speeds_auto">Avtomatik</string>
<string name="revanced_custom_playback_speeds_reset_toast">Oynatma sürəti sıfırlandı: %s</string>
<string name="revanced_speed_tap_and_hold_title">Xüsusi toxunma və saxlanılma sürəti</string> <string name="revanced_speed_tap_and_hold_title">Xüsusi toxunma və saxlanılma sürəti</string>
<string name="revanced_speed_tap_and_hold_summary">0-8 arası oynatma sürəti</string> <string name="revanced_speed_tap_and_hold_summary">0-8 arası oynatma sürəti</string>
</patch> </patch>
@@ -1490,7 +1483,6 @@ AVC maksimum 1080p görüntü imkanına malikdir, Opus audio kodlama olmur və v
<string name="revanced_embedded_ads_service_failed">%s xəta qaytardı, reklamlar görünə bilər. Tənzimləmədə reklam əngəlləmə xidmətin dəyişməyə çalışın.</string> <string name="revanced_embedded_ads_service_failed">%s xəta qaytardı, reklamlar görünə bilər. Tənzimləmədə reklam əngəlləmə xidmətin dəyişməyə çalışın.</string>
<string name="revanced_block_embedded_ads_title">Yerləşdirilən video reklamlarını əngəllə</string> <string name="revanced_block_embedded_ads_title">Yerləşdirilən video reklamlarını əngəllə</string>
<string name="revanced_block_embedded_ads_entry_1">Qeyri-aktiv edildi</string> <string name="revanced_block_embedded_ads_entry_1">Qeyri-aktiv edildi</string>
<string name="revanced_block_embedded_ads_entry_2">Luminous proxy</string>
<string name="revanced_block_embedded_ads_entry_3">PurpleAdBlock proksi</string> <string name="revanced_block_embedded_ads_entry_3">PurpleAdBlock proksi</string>
</patch> </patch>
<patch id="ad.video.videoAdsPatch"> <patch id="ad.video.videoAdsPatch">

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