Compare commits

...

22 Commits

Author SHA1 Message Date
semantic-release-bot
cd467d6244 chore: Release v5.19.0-dev.2 [skip ci]
# [5.19.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.19.0-dev.1...v5.19.0-dev.2) (2025-04-02)

### Features

* **YouTube - Settings:** Add icons to the ReVanced settings ([#4496](https://github.com/ReVanced/revanced-patches/issues/4496)) ([fdefb67](fdefb67d02))
2025-04-02 09:42:46 +00:00
MarcaD
fdefb67d02 feat(YouTube - Settings): Add icons to the ReVanced settings (#4496) 2025-04-02 11:39:53 +02:00
semantic-release-bot
5274cd18f0 chore: Release v5.19.0-dev.1 [skip ci]
# [5.19.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.18.1-dev.2...v5.19.0-dev.1) (2025-04-01)

### Bug Fixes

* **Twitter - Hide recommended users:** Make hiding work again by filtering for new entryId prefix ([#4456](https://github.com/ReVanced/revanced-patches/issues/4456)) ([3d68c06](3d68c06146))

### Features

* **Angulus:** Add `Hide ads` patch ([#4604](https://github.com/ReVanced/revanced-patches/issues/4604)) ([2d7b1b0](2d7b1b09af))
* **Photomath:** Support latest version ([#4672](https://github.com/ReVanced/revanced-patches/issues/4672)) ([ef3d5ba](ef3d5bafd5))
2025-04-01 22:33:38 +00:00
Jakub Blažej
3d68c06146 fix(Twitter - Hide recommended users): Make hiding work again by filtering for new entryId prefix (#4456) 2025-04-02 00:31:02 +02:00
Dawid Krajcarz
ef3d5bafd5 feat(Photomath): Support latest version (#4672) 2025-04-02 00:28:57 +02:00
Denis Kerner
2d7b1b09af feat(Angulus): Add Hide ads patch (#4604)
Co-authored-by: Denis Kerner <denis.kerner@vodafone.com>
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2025-04-02 00:27:59 +02:00
semantic-release-bot
0572d48fde chore: Release v5.18.1-dev.2 [skip ci]
## [5.18.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.18.1-dev.1...v5.18.1-dev.2) (2025-04-01)

### Bug Fixes

* **YouTube:** Combine multiple seekbar patches into a single patch ([#4705](https://github.com/ReVanced/revanced-patches/issues/4705)) ([37984b8](37984b8b99))
2025-04-01 19:00:31 +00:00
LisoUseInAIKyrios
37984b8b99 fix(YouTube): Combine multiple seekbar patches into a single patch (#4705) 2025-04-01 20:57:03 +02:00
github-actions[bot]
6e63193f06 chore: Sync translations (#4713) 2025-04-01 20:51:16 +02:00
LisoUseInAIKyrios
b2384b22a5 refactor: Add more opcodes to findFreeRegister 2025-04-01 20:17:00 +02:00
semantic-release-bot
ccb76983ff chore: Release v5.18.1-dev.1 [skip ci]
## [5.18.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.18.0...v5.18.1-dev.1) (2025-03-31)

### Bug Fixes

* **YouTube - Remove background playback restrictions:** Do not show media controls when playing Shorts from the feed ([318b55b](318b55b8fe))
2025-03-31 13:45:18 +00:00
LisoUseInAIKyrios
318b55b8fe fix(YouTube - Remove background playback restrictions): Do not show media controls when playing Shorts from the feed 2025-03-31 15:36:01 +02:00
github-actions[bot]
49ade9efbc chore: Sync translations (#4703) 2025-03-31 15:35:28 +02:00
LisoUseInAIKyrios
d77515bd68 refactor: Add helper method to find a free register for a specific insert index (#4693) 2025-03-30 18:37:54 +02:00
semantic-release-bot
087bf1e152 chore: Release v5.18.0 [skip ci]
# [5.18.0](https://github.com/ReVanced/revanced-patches/compare/v5.17.0...v5.18.0) (2025-03-28)

### Bug Fixes

* **Spotify:** Ignore optional attributes if not present ([#4688](https://github.com/ReVanced/revanced-patches/issues/4688)) ([84f5854](84f585492e))

### Features

* **YouTube:** Support version `20.07.39` ([#4677](https://github.com/ReVanced/revanced-patches/issues/4677)) ([842ba4f](842ba4fc4d))
2025-03-28 18:51:44 +00:00
LisoUseInAIKyrios
c2994d583d chore: Merge branch dev to main (#4686) 2025-03-28 19:48:32 +01:00
semantic-release-bot
127b0a63fe chore: Release v5.18.0-dev.2 [skip ci]
# [5.18.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.18.0-dev.1...v5.18.0-dev.2) (2025-03-28)

### Bug Fixes

* **Spotify:** Ignore optional attributes if not present ([#4688](https://github.com/ReVanced/revanced-patches/issues/4688)) ([84f5854](84f585492e))
2025-03-28 18:36:38 +00:00
github-actions[bot]
27aafd0ee1 chore: Sync translations (#4689) 2025-03-28 19:31:52 +01:00
semantic-release-bot
49c54c0e54 chore: Release v5.18.0-dev.1 [skip ci]
# [5.18.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.17.0...v5.18.0-dev.1) (2025-03-28)

### Features

* **YouTube:** Support version `20.07.39` ([#4677](https://github.com/ReVanced/revanced-patches/issues/4677)) ([842ba4f](842ba4fc4d))
2025-03-28 17:01:42 +00:00
LisoUseInAIKyrios
842ba4fc4d feat(YouTube): Support version 20.07.39 (#4677) 2025-03-28 17:49:12 +01:00
semantic-release-bot
66ecadce4f chore: Release v5.17.0 [skip ci]
# [5.17.0](https://github.com/ReVanced/revanced-patches/compare/v5.16.1...v5.17.0) (2025-03-28)

### Bug Fixes

* **Facebook - Hide 'Sponsored Stories':** Constrain patch to latest compatible version ([#4657](https://github.com/ReVanced/revanced-patches/issues/4657)) ([4d910fe](4d910fea93))
* **Spotify - Unlock Premium:** Override additional attributes ([#4651](https://github.com/ReVanced/revanced-patches/issues/4651)) ([ca4f960](ca4f960171))
* **Spotify - Unlock Premium:** Use correct patch description convention ([a486522](a4865228f8))
* **X / Twitter:** Constrain patches to latest compatible versions ([#4683](https://github.com/ReVanced/revanced-patches/issues/4683)) ([497291c](497291c478))
* **YouTube - Navigation buttons:** Add user dialog message to 'Disable translucent status bar' ([bf91e12](bf91e127d8))

### Features

* **Spotify - Unlock Premium:** Disable the "Spotify Premium" upsell experiment in context menus ([c84be12](c84be120bd))
2025-03-28 16:39:31 +00:00
LisoUseInAIKyrios
73ca04da5e chore: Merge branch dev to main (#4658) 2025-03-28 17:36:31 +01:00
183 changed files with 1974 additions and 968 deletions

View File

@@ -1,3 +1,79 @@
# [5.19.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.19.0-dev.1...v5.19.0-dev.2) (2025-04-02)
### Features
* **YouTube - Settings:** Add icons to the ReVanced settings ([#4496](https://github.com/ReVanced/revanced-patches/issues/4496)) ([d0c85f0](https://github.com/ReVanced/revanced-patches/commit/d0c85f044083d720c63a8ea4ff15d42eefeb9db7))
# [5.19.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.18.1-dev.2...v5.19.0-dev.1) (2025-04-01)
### Bug Fixes
* **Twitter - Hide recommended users:** Make hiding work again by filtering for new entryId prefix ([#4456](https://github.com/ReVanced/revanced-patches/issues/4456)) ([ff846b0](https://github.com/ReVanced/revanced-patches/commit/ff846b0b7ef5060caaffedb08c1f901172f5b2d1))
### Features
* **Angulus:** Add `Hide ads` patch ([#4604](https://github.com/ReVanced/revanced-patches/issues/4604)) ([87c86b5](https://github.com/ReVanced/revanced-patches/commit/87c86b53a91b0054ac892a3f02bbe7bf83bbf813))
* **Photomath:** Support latest version ([#4672](https://github.com/ReVanced/revanced-patches/issues/4672)) ([8e16483](https://github.com/ReVanced/revanced-patches/commit/8e1648322948151e4565fb0d86e0f37d0a02d73f))
## [5.18.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.18.1-dev.1...v5.18.1-dev.2) (2025-04-01)
### Bug Fixes
* **YouTube:** Combine multiple seekbar patches into a single patch ([#4705](https://github.com/ReVanced/revanced-patches/issues/4705)) ([503b7eb](https://github.com/ReVanced/revanced-patches/commit/503b7eb8d413ef7f248394f128f3b2a6f3192ba6))
## [5.18.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.18.0...v5.18.1-dev.1) (2025-03-31)
### Bug Fixes
* **YouTube - Remove background playback restrictions:** Do not show media controls when playing Shorts from the feed ([2ed675c](https://github.com/ReVanced/revanced-patches/commit/2ed675cdd058fb5876381a9d30dee5263f6b2e26))
# [5.18.0](https://github.com/ReVanced/revanced-patches/compare/v5.17.0...v5.18.0) (2025-03-28)
### Bug Fixes
* **Spotify:** Ignore optional attributes if not present ([#4688](https://github.com/ReVanced/revanced-patches/issues/4688)) ([84f5854](https://github.com/ReVanced/revanced-patches/commit/84f585492e4be3604c6c7680ffb3bebcea5a675f))
### Features
* **YouTube:** Support version `20.07.39` ([#4677](https://github.com/ReVanced/revanced-patches/issues/4677)) ([c1379f6](https://github.com/ReVanced/revanced-patches/commit/c1379f6e520c683d2c9d6a490a69ca542168b3b3))
# [5.18.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.18.0-dev.1...v5.18.0-dev.2) (2025-03-28)
### Bug Fixes
* **Spotify:** Ignore optional attributes if not present ([#4688](https://github.com/ReVanced/revanced-patches/issues/4688)) ([84f5854](https://github.com/ReVanced/revanced-patches/commit/84f585492e4be3604c6c7680ffb3bebcea5a675f))
# [5.18.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.17.0...v5.18.0-dev.1) (2025-03-28)
### Features
* **YouTube:** Support version `20.07.39` ([#4677](https://github.com/ReVanced/revanced-patches/issues/4677)) ([c1379f6](https://github.com/ReVanced/revanced-patches/commit/c1379f6e520c683d2c9d6a490a69ca542168b3b3))
# [5.17.0](https://github.com/ReVanced/revanced-patches/compare/v5.16.1...v5.17.0) (2025-03-28)
### Bug Fixes
* **Facebook - Hide 'Sponsored Stories':** Constrain patch to latest compatible version ([#4657](https://github.com/ReVanced/revanced-patches/issues/4657)) ([46bd1c8](https://github.com/ReVanced/revanced-patches/commit/46bd1c829acd5f83600025e0ceb7d482ae80be69))
* **Spotify - Unlock Premium:** Override additional attributes ([#4651](https://github.com/ReVanced/revanced-patches/issues/4651)) ([568b40d](https://github.com/ReVanced/revanced-patches/commit/568b40da9692eae9039bbb3cec513a61ca627c24))
* **Spotify - Unlock Premium:** Use correct patch description convention ([a486522](https://github.com/ReVanced/revanced-patches/commit/a4865228f8481d2efc8fbf4e90902a03289d9a3f))
* **X / Twitter:** Constrain patches to latest compatible versions ([#4683](https://github.com/ReVanced/revanced-patches/issues/4683)) ([f579728](https://github.com/ReVanced/revanced-patches/commit/f5797289f45186052537982c7f5db6f2b0769aee))
* **YouTube - Navigation buttons:** Add user dialog message to 'Disable translucent status bar' ([a4a0e68](https://github.com/ReVanced/revanced-patches/commit/a4a0e6869e23d15ee09262460f4e290c90629eeb))
### Features
* **Spotify - Unlock Premium:** Disable the "Spotify Premium" upsell experiment in context menus ([9a10ee4](https://github.com/ReVanced/revanced-patches/commit/9a10ee4d22fb53da2012a182e038749d3ad72377))
# [5.17.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.17.0-dev.3...v5.17.0-dev.4) (2025-03-28) # [5.17.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.17.0-dev.3...v5.17.0-dev.4) (2025-03-28)

View File

@@ -23,6 +23,11 @@ public class BaseSettings {
public static final EnumSetting<AppLanguage> REVANCED_LANGUAGE = new EnumSetting<>("revanced_language", AppLanguage.DEFAULT, true, "revanced_language_user_dialog_message"); public static final EnumSetting<AppLanguage> REVANCED_LANGUAGE = new EnumSetting<>("revanced_language", AppLanguage.DEFAULT, true, "revanced_language_user_dialog_message");
/**
* Use the icons declared in the preferences created during patching. If no icons or styles are declared then this setting does nothing.
*/
public static final BooleanSetting SHOW_MENU_ICONS = new BooleanSetting("revanced_show_menu_icons", TRUE, true);
public static final BooleanSetting SPOOF_VIDEO_STREAMS = new BooleanSetting("revanced_spoof_video_streams", TRUE, true, "revanced_spoof_video_streams_user_dialog_message"); public static final BooleanSetting SPOOF_VIDEO_STREAMS = new BooleanSetting("revanced_spoof_video_streams", TRUE, true, "revanced_spoof_video_streams_user_dialog_message");
public static final EnumSetting<AppLanguage> SPOOF_VIDEO_STREAMS_LANGUAGE = new EnumSetting<>("revanced_spoof_video_streams_language", AppLanguage.DEFAULT, new AudioStreamLanguageOverrideAvailability()); public static final EnumSetting<AppLanguage> SPOOF_VIDEO_STREAMS_LANGUAGE = new EnumSetting<>("revanced_spoof_video_streams_language", AppLanguage.DEFAULT, new AudioStreamLanguageOverrideAvailability());
public static final BooleanSetting SPOOF_STREAMING_DATA_STATS_FOR_NERDS = new BooleanSetting("revanced_spoof_streaming_data_stats_for_nerds", TRUE, parent(SPOOF_VIDEO_STREAMS)); public static final BooleanSetting SPOOF_STREAMING_DATA_STATS_FOR_NERDS = new BooleanSetting("revanced_spoof_streaming_data_stats_for_nerds", TRUE, parent(SPOOF_VIDEO_STREAMS));

View File

@@ -86,7 +86,6 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
} }
}; };
/** /**
* Initialize this instance, and do any custom behavior. * Initialize this instance, and do any custom behavior.
* <p> * <p>
@@ -95,7 +94,10 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
* so all app specific {@link Setting} instances are loaded before this method returns. * so all app specific {@link Setting} instances are loaded before this method returns.
*/ */
protected void initialize() { protected void initialize() {
final var identifier = Utils.getResourceIdentifier("revanced_prefs", "xml"); String preferenceResourceName = BaseSettings.SHOW_MENU_ICONS.get()
? "revanced_prefs_icons"
: "revanced_prefs";
final var identifier = Utils.getResourceIdentifier(preferenceResourceName, "xml");
if (identifier == 0) return; if (identifier == 0) return;
addPreferencesFromResource(identifier); addPreferencesFromResource(identifier);

View File

@@ -122,6 +122,21 @@ public class SpoofVideoStreamsPatch {
return false; return false;
} }
/**
* Injection point.
* Turns off a feature flag that interferes with video playback.
*/
public static boolean usePlaybackStartFeatureFlag(boolean original) {
if (original) {
Logger.printDebug(() -> "usePlaybackStartFeatureFlag is set on");
}
if (!SPOOF_STREAMING_DATA) {
return original;
}
return false;
}
/** /**
* Injection point. * Injection point.
*/ */

View File

@@ -9,7 +9,6 @@ import app.revanced.extension.tiktok.settings.preference.categories.DownloadsPre
import app.revanced.extension.tiktok.settings.preference.categories.FeedFilterPreferenceCategory; import app.revanced.extension.tiktok.settings.preference.categories.FeedFilterPreferenceCategory;
import app.revanced.extension.tiktok.settings.preference.categories.ExtensionPreferenceCategory; import app.revanced.extension.tiktok.settings.preference.categories.ExtensionPreferenceCategory;
import app.revanced.extension.tiktok.settings.preference.categories.SimSpoofPreferenceCategory; import app.revanced.extension.tiktok.settings.preference.categories.SimSpoofPreferenceCategory;
import org.jetbrains.annotations.NotNull;
/** /**
* Preference fragment for ReVanced settings * Preference fragment for ReVanced settings

View File

@@ -163,7 +163,7 @@ internal object TwiFucker {
private fun JSONObject.entryIsWhoToFollow(): Boolean = private fun JSONObject.entryIsWhoToFollow(): Boolean =
optString("entryId").let { optString("entryId").let {
it.startsWith("whoToFollow-") || it.startsWith("who-to-follow-") || it.startsWith("connect-module-") it.startsWith("whoToFollow-") || it.startsWith("who-to-follow-") || it.startsWith("connect-module-") || it.startsWith("who-to-subscribe-")
} }
private fun JSONObject.itemContainsPromotedUser(): Boolean = private fun JSONObject.itemContainsPromotedUser(): Boolean =

View File

@@ -1,6 +1,7 @@
package app.revanced.extension.youtube.patches; package app.revanced.extension.youtube.patches;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.PlayerType;
import app.revanced.extension.youtube.shared.ShortsPlayerState; import app.revanced.extension.youtube.shared.ShortsPlayerState;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@@ -23,7 +24,13 @@ public class BackgroundPlaybackPatch {
// 7. Close the Short // 7. Close the Short
// 8. Resume playing the regular video // 8. Resume playing the regular video
// 9. Minimize the app (PIP should appear) // 9. Minimize the app (PIP should appear)
return !ShortsPlayerState.isOpen(); if (ShortsPlayerState.isOpen()) {
return false;
}
// Check if the video player is opened and it's not playing in the feed.
PlayerType current = PlayerType.getCurrent();
return !current.isNoneOrHidden() && current != PlayerType.INLINE_MINIMAL;
} }
/** /**

View File

@@ -2,7 +2,7 @@ package app.revanced.extension.youtube.patches;
import app.revanced.extension.youtube.settings.Settings; import app.revanced.extension.youtube.settings.Settings;
/** @noinspection unused*/ @SuppressWarnings("unused")
public class DisableResumingStartupShortsPlayerPatch { public class DisableResumingStartupShortsPlayerPatch {
/** /**
@@ -11,4 +11,11 @@ public class DisableResumingStartupShortsPlayerPatch {
public static boolean disableResumingStartupShortsPlayer() { public static boolean disableResumingStartupShortsPlayer() {
return Settings.DISABLE_RESUMING_SHORTS_PLAYER.get(); return Settings.DISABLE_RESUMING_SHORTS_PLAYER.get();
} }
/**
* Injection point.
*/
public static boolean disableResumingStartupShortsPlayer(boolean original) {
return original && !Settings.DISABLE_RESUMING_SHORTS_PLAYER.get();
}
} }

View File

@@ -43,10 +43,13 @@ public final class MiniplayerPatch {
MODERN_2(null, 2), MODERN_2(null, 2),
MODERN_3(null, 3), MODERN_3(null, 3),
/** /**
* Half broken miniplayer, that might be work in progress or left over abandoned code. * Works and is functional with 20.03+
* Can force this type by editing the import/export settings.
*/ */
MODERN_4(null, 4); MODERN_4(null, 4),
/**
* Half broken miniplayer, and in 20.02 and earlier is declared as type 4.
*/
MODERN_5(null, 5);
/** /**
* Legacy tablet hook value. * Legacy tablet hook value.
@@ -126,12 +129,13 @@ public final class MiniplayerPatch {
private static final boolean DRAG_AND_DROP_ENABLED = private static final boolean DRAG_AND_DROP_ENABLED =
CURRENT_TYPE.isModern() && Settings.MINIPLAYER_DRAG_AND_DROP.get(); CURRENT_TYPE.isModern() && Settings.MINIPLAYER_DRAG_AND_DROP.get();
private static final boolean HIDE_EXPAND_CLOSE_ENABLED = private static final boolean HIDE_OVERLAY_BUTTONS_ENABLED =
Settings.MINIPLAYER_HIDE_EXPAND_CLOSE.get() Settings.MINIPLAYER_HIDE_OVERLAY_BUTTONS.get()
&& Settings.MINIPLAYER_HIDE_EXPAND_CLOSE.isAvailable(); && Settings.MINIPLAYER_HIDE_OVERLAY_BUTTONS.isAvailable();
private static final boolean HIDE_SUBTEXT_ENABLED = private static final boolean HIDE_SUBTEXT_ENABLED =
(CURRENT_TYPE == MODERN_1 || CURRENT_TYPE == MODERN_3) && Settings.MINIPLAYER_HIDE_SUBTEXT.get(); (CURRENT_TYPE == MODERN_1 || CURRENT_TYPE == MODERN_3 || CURRENT_TYPE == MODERN_4)
&& Settings.MINIPLAYER_HIDE_SUBTEXT.get();
// 19.25 is last version that has forward/back buttons for phones, // 19.25 is last version that has forward/back buttons for phones,
// but buttons still show for tablets/foldable devices and they don't work well so always hide. // but buttons still show for tablets/foldable devices and they don't work well so always hide.
@@ -139,7 +143,7 @@ public final class MiniplayerPatch {
&& (VersionCheckPatch.IS_19_34_OR_GREATER || Settings.MINIPLAYER_HIDE_REWIND_FORWARD.get()); && (VersionCheckPatch.IS_19_34_OR_GREATER || Settings.MINIPLAYER_HIDE_REWIND_FORWARD.get());
private static final boolean MINIPLAYER_ROUNDED_CORNERS_ENABLED = private static final boolean MINIPLAYER_ROUNDED_CORNERS_ENABLED =
Settings.MINIPLAYER_ROUNDED_CORNERS.get(); CURRENT_TYPE.isModern() && Settings.MINIPLAYER_ROUNDED_CORNERS.get();
private static final boolean MINIPLAYER_HORIZONTAL_DRAG_ENABLED = private static final boolean MINIPLAYER_HORIZONTAL_DRAG_ENABLED =
DRAG_AND_DROP_ENABLED && Settings.MINIPLAYER_HORIZONTAL_DRAG.get(); DRAG_AND_DROP_ENABLED && Settings.MINIPLAYER_HORIZONTAL_DRAG.get();
@@ -172,11 +176,12 @@ public final class MiniplayerPatch {
} }
} }
public static final class MiniplayerHideExpandCloseAvailability implements Setting.Availability { public static final class MiniplayerHideOverlayButtonsAvailability implements Setting.Availability {
@Override @Override
public boolean isAvailable() { public boolean isAvailable() {
MiniplayerType type = Settings.MINIPLAYER_TYPE.get(); MiniplayerType type = Settings.MINIPLAYER_TYPE.get();
return (!IS_19_20_OR_GREATER && (type == MODERN_1 || type == MODERN_3)) return type == MODERN_4
|| (!IS_19_20_OR_GREATER && (type == MODERN_1 || type == MODERN_3))
|| (!IS_19_26_OR_GREATER && type == MODERN_1 || (!IS_19_26_OR_GREATER && type == MODERN_1
&& !Settings.MINIPLAYER_DOUBLE_TAP_ACTION.get() && !Settings.MINIPLAYER_DRAG_AND_DROP.get()) && !Settings.MINIPLAYER_DOUBLE_TAP_ACTION.get() && !Settings.MINIPLAYER_DRAG_AND_DROP.get())
|| (IS_19_29_OR_GREATER && type == MODERN_3); || (IS_19_29_OR_GREATER && type == MODERN_3);
@@ -227,9 +232,13 @@ public final class MiniplayerPatch {
/** /**
* Injection point. * Injection point.
*/ */
public static void adjustMiniplayerOpacity(ImageView view) { public static void adjustMiniplayerOpacity(View view) {
if (CURRENT_TYPE == MODERN_1) { if (CURRENT_TYPE == MODERN_1) {
view.setImageAlpha(OPACITY_LEVEL); if (view instanceof ImageView imageView) {
imageView.setImageAlpha(OPACITY_LEVEL);
} else {
Logger.printException(() -> "Unknown miniplayer overlay view: " + view);
}
} }
} }
@@ -247,7 +256,7 @@ public final class MiniplayerPatch {
/** /**
* Injection point. * Injection point.
*/ */
public static boolean enableMiniplayerDoubleTapAction(boolean original) { public static boolean getMiniplayerDoubleTapAction(boolean original) {
if (CURRENT_TYPE == DEFAULT) { if (CURRENT_TYPE == DEFAULT) {
return original; return original;
} }
@@ -258,7 +267,7 @@ public final class MiniplayerPatch {
/** /**
* Injection point. * Injection point.
*/ */
public static boolean enableMiniplayerDragAndDrop(boolean original) { public static boolean getMiniplayerDragAndDrop(boolean original) {
if (CURRENT_TYPE == DEFAULT) { if (CURRENT_TYPE == DEFAULT) {
return original; return original;
} }
@@ -266,13 +275,36 @@ public final class MiniplayerPatch {
return DRAG_AND_DROP_ENABLED; return DRAG_AND_DROP_ENABLED;
} }
/**
* Injection point.
*/
public static boolean getRoundedCorners(boolean original) {
if (CURRENT_TYPE == DEFAULT) {
return original;
}
return MINIPLAYER_ROUNDED_CORNERS_ENABLED;
}
/** /**
* Injection point. * Injection point.
*/ */
public static boolean setRoundedCorners(boolean original) { public static boolean getHorizontalDrag(boolean original) {
if (CURRENT_TYPE.isModern()) { if (CURRENT_TYPE == DEFAULT) {
return MINIPLAYER_ROUNDED_CORNERS_ENABLED; return original;
}
return MINIPLAYER_HORIZONTAL_DRAG_ENABLED;
}
/**
* Injection point.
*/
public static boolean getMaximizeAnimation(boolean original) {
// This must be forced on if horizontal drag is enabled,
// otherwise the UI has visual glitches when maximizing the miniplayer.
if (MINIPLAYER_HORIZONTAL_DRAG_ENABLED) {
return true;
} }
return original; return original;
@@ -281,7 +313,7 @@ public final class MiniplayerPatch {
/** /**
* Injection point. * Injection point.
*/ */
public static int setMiniplayerDefaultSize(int original) { public static int getMiniplayerDefaultSize(int original) {
if (CURRENT_TYPE.isModern()) { if (CURRENT_TYPE.isModern()) {
return MINIPLAYER_SIZE; return MINIPLAYER_SIZE;
} }
@@ -289,29 +321,26 @@ public final class MiniplayerPatch {
return original; return original;
} }
/**
* Injection point.
*/
public static void hideMiniplayerExpandClose(View view) {
Utils.hideViewByRemovingFromParentUnderCondition(HIDE_OVERLAY_BUTTONS_ENABLED, view);
}
/** /**
* Injection point. * Injection point.
*/ */
public static boolean setHorizontalDrag(boolean original) { public static void hideMiniplayerActionButton(View view) {
if (CURRENT_TYPE.isModern()) { if (CURRENT_TYPE == MODERN_4) {
return MINIPLAYER_HORIZONTAL_DRAG_ENABLED; Utils.hideViewByRemovingFromParentUnderCondition(HIDE_OVERLAY_BUTTONS_ENABLED, view);
} }
return original;
} }
/** /**
* Injection point. * Injection point.
*/ */
public static void hideMiniplayerExpandClose(ImageView view) { public static void hideMiniplayerRewindForward(View view) {
Utils.hideViewByRemovingFromParentUnderCondition(HIDE_EXPAND_CLOSE_ENABLED, view);
}
/**
* Injection point.
*/
public static void hideMiniplayerRewindForward(ImageView view) {
Utils.hideViewByRemovingFromParentUnderCondition(HIDE_REWIND_FORWARD_ENABLED, view); Utils.hideViewByRemovingFromParentUnderCondition(HIDE_REWIND_FORWARD_ENABLED, view);
} }

View File

@@ -3,11 +3,15 @@ package app.revanced.extension.youtube.patches;
import app.revanced.extension.shared.Utils; import app.revanced.extension.shared.Utils;
public class VersionCheckPatch { public class VersionCheckPatch {
public static final boolean IS_19_17_OR_GREATER = Utils.getAppVersionName().compareTo("19.17.00") >= 0; private static boolean isVersionOrGreater(String version) {
public static final boolean IS_19_20_OR_GREATER = Utils.getAppVersionName().compareTo("19.20.00") >= 0; return Utils.getAppVersionName().compareTo(version) >= 0;
public static final boolean IS_19_21_OR_GREATER = Utils.getAppVersionName().compareTo("19.21.00") >= 0; }
public static final boolean IS_19_26_OR_GREATER = Utils.getAppVersionName().compareTo("19.26.00") >= 0;
public static final boolean IS_19_29_OR_GREATER = Utils.getAppVersionName().compareTo("19.29.00") >= 0; public static final boolean IS_19_17_OR_GREATER = isVersionOrGreater("19.17.00");
public static final boolean IS_19_34_OR_GREATER = Utils.getAppVersionName().compareTo("19.34.00") >= 0; public static final boolean IS_19_20_OR_GREATER = isVersionOrGreater("19.20.00");
public static final boolean IS_19_46_OR_GREATER = Utils.getAppVersionName().compareTo("19.46.00") >= 0; public static final boolean IS_19_21_OR_GREATER = isVersionOrGreater("19.21.00");
public static final boolean IS_19_26_OR_GREATER = isVersionOrGreater("19.26.00");
public static final boolean IS_19_29_OR_GREATER = isVersionOrGreater("19.29.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");
} }

View File

@@ -114,7 +114,7 @@ public class ReturnYouTubeDislike {
private static final Rect middleSeparatorBounds; private static final Rect middleSeparatorBounds;
/** /**
* Left separator horizontal padding for Rolling Number layout. * Horizontal padding between the left and middle separator.
*/ */
public static final int leftSeparatorShapePaddingPixels; public static final int leftSeparatorShapePaddingPixels;
private static final ShapeDrawable leftSeparatorShape; private static final ShapeDrawable leftSeparatorShape;
@@ -129,7 +129,7 @@ public class ReturnYouTubeDislike {
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3.7f, dp); (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3.7f, dp);
middleSeparatorBounds = new Rect(0, 0, middleSeparatorSize, middleSeparatorSize); middleSeparatorBounds = new Rect(0, 0, middleSeparatorSize, middleSeparatorSize);
leftSeparatorShapePaddingPixels = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10.0f, dp); leftSeparatorShapePaddingPixels = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8.4f, dp);
leftSeparatorShape = new ShapeDrawable(new RectShape()); leftSeparatorShape = new ShapeDrawable(new RectShape());
leftSeparatorShape.setBounds(leftSeparatorBounds); leftSeparatorShape.setBounds(leftSeparatorBounds);
@@ -238,7 +238,7 @@ public class ReturnYouTubeDislike {
String leftSeparatorString = getTextDirectionString(); String leftSeparatorString = getTextDirectionString();
final Spannable leftSeparatorSpan; final Spannable leftSeparatorSpan;
if (isRollingNumber) { if (isRollingNumber) {
leftSeparatorSpan = new SpannableString(leftSeparatorString); leftSeparatorSpan = new SpannableString(leftSeparatorString);
} else { } else {
leftSeparatorString += " "; leftSeparatorString += " ";
leftSeparatorSpan = new SpannableString(leftSeparatorString); leftSeparatorSpan = new SpannableString(leftSeparatorString);
@@ -623,7 +623,7 @@ public class ReturnYouTubeDislike {
userVote = vote; userVote = vote;
clearUICache(); clearUICache();
} }
if (future.isDone()) { if (future.isDone()) {
// Update the fetched vote data. // Update the fetched vote data.
RYDVoteData voteData = getFetchData(MAX_MILLISECONDS_TO_BLOCK_UI_WAITING_FOR_FETCH); RYDVoteData voteData = getFetchData(MAX_MILLISECONDS_TO_BLOCK_UI_WAITING_FOR_FETCH);

View File

@@ -10,7 +10,6 @@ import static app.revanced.extension.youtube.patches.ChangeFormFactorPatch.FormF
import static app.revanced.extension.youtube.patches.ChangeStartPagePatch.StartPage; import static app.revanced.extension.youtube.patches.ChangeStartPagePatch.StartPage;
import static app.revanced.extension.youtube.patches.ExitFullscreenPatch.FullscreenMode; import static app.revanced.extension.youtube.patches.ExitFullscreenPatch.FullscreenMode;
import static app.revanced.extension.youtube.patches.ForceOriginalAudioPatch.ForceOriginalAudioAvailability; import static app.revanced.extension.youtube.patches.ForceOriginalAudioPatch.ForceOriginalAudioAvailability;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHideExpandCloseAvailability;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHorizontalDragAvailability; import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHorizontalDragAvailability;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType; import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MINIMAL; import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MINIMAL;
@@ -40,6 +39,7 @@ import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.DeArrow
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.StillImagesAvailability; import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.StillImagesAvailability;
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.ThumbnailOption; import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.ThumbnailOption;
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.ThumbnailStillTime; import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.ThumbnailStillTime;
import app.revanced.extension.youtube.patches.MiniplayerPatch;
import app.revanced.extension.youtube.sponsorblock.SponsorBlockSettings; import app.revanced.extension.youtube.sponsorblock.SponsorBlockSettings;
public class Settings extends BaseSettings { public class Settings extends BaseSettings {
@@ -156,7 +156,7 @@ public class Settings extends BaseSettings {
public static final BooleanSetting MINIPLAYER_DOUBLE_TAP_ACTION = new BooleanSetting("revanced_miniplayer_double_tap_action", TRUE, true, MINIPLAYER_ANY_MODERN); public static final BooleanSetting MINIPLAYER_DOUBLE_TAP_ACTION = new BooleanSetting("revanced_miniplayer_double_tap_action", TRUE, true, MINIPLAYER_ANY_MODERN);
public static final BooleanSetting MINIPLAYER_DRAG_AND_DROP = new BooleanSetting("revanced_miniplayer_drag_and_drop", TRUE, true, MINIPLAYER_ANY_MODERN); public static final BooleanSetting MINIPLAYER_DRAG_AND_DROP = new BooleanSetting("revanced_miniplayer_drag_and_drop", TRUE, true, MINIPLAYER_ANY_MODERN);
public static final BooleanSetting MINIPLAYER_HORIZONTAL_DRAG = new BooleanSetting("revanced_miniplayer_horizontal_drag", FALSE, true, new MiniplayerHorizontalDragAvailability()); public static final BooleanSetting MINIPLAYER_HORIZONTAL_DRAG = new BooleanSetting("revanced_miniplayer_horizontal_drag", FALSE, true, new MiniplayerHorizontalDragAvailability());
public static final BooleanSetting MINIPLAYER_HIDE_EXPAND_CLOSE = new BooleanSetting("revanced_miniplayer_hide_expand_close", FALSE, true, new MiniplayerHideExpandCloseAvailability()); public static final BooleanSetting MINIPLAYER_HIDE_OVERLAY_BUTTONS = new BooleanSetting("revanced_miniplayer_hide_overlay_buttons", FALSE, true, new MiniplayerPatch.MiniplayerHideOverlayButtonsAvailability());
public static final BooleanSetting MINIPLAYER_HIDE_SUBTEXT = new BooleanSetting("revanced_miniplayer_hide_subtext", FALSE, true, MINIPLAYER_TYPE.availability(MODERN_1, MODERN_3)); public static final BooleanSetting MINIPLAYER_HIDE_SUBTEXT = new BooleanSetting("revanced_miniplayer_hide_subtext", FALSE, true, MINIPLAYER_TYPE.availability(MODERN_1, MODERN_3));
public static final BooleanSetting MINIPLAYER_HIDE_REWIND_FORWARD = new BooleanSetting("revanced_miniplayer_hide_rewind_forward", TRUE, true, MINIPLAYER_TYPE.availability(MODERN_1)); public static final BooleanSetting MINIPLAYER_HIDE_REWIND_FORWARD = new BooleanSetting("revanced_miniplayer_hide_rewind_forward", TRUE, true, MINIPLAYER_TYPE.availability(MODERN_1));
public static final BooleanSetting MINIPLAYER_ROUNDED_CORNERS = new BooleanSetting("revanced_miniplayer_rounded_corners", TRUE, true, MINIPLAYER_ANY_MODERN); public static final BooleanSetting MINIPLAYER_ROUNDED_CORNERS = new BooleanSetting("revanced_miniplayer_rounded_corners", TRUE, true, MINIPLAYER_ANY_MODERN);

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.17.0-dev.4 version = 5.19.0-dev.2

View File

@@ -132,6 +132,10 @@ public final class app/revanced/patches/amazon/DeepLinkingPatchKt {
public static final fun getDeepLinkingPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getDeepLinkingPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
} }
public final class app/revanced/patches/angulus/ads/RemoveAdsPatchKt {
public static final fun getAngulusPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/backdrops/misc/pro/ProUnlockPatchKt { public final class app/revanced/patches/backdrops/misc/pro/ProUnlockPatchKt {
public static final fun getProUnlockPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getProUnlockPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
} }
@@ -776,8 +780,8 @@ public final class app/revanced/patches/shared/misc/settings/preference/TextPref
} }
public final class app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatchKt { public final class app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatchKt {
public static final fun spoofVideoStreamsPatch (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/BytecodePatch; public static final fun spoofVideoStreamsPatch (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/BytecodePatch;
public static synthetic fun spoofVideoStreamsPatch$default (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/BytecodePatch; public static synthetic fun spoofVideoStreamsPatch$default (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/BytecodePatch;
} }
public final class app/revanced/patches/shared/misc/spoof/UserAgentClientSpoofPatchKt { public final class app/revanced/patches/shared/misc/spoof/UserAgentClientSpoofPatchKt {
@@ -1096,6 +1100,14 @@ public final class app/revanced/patches/youtube/interaction/seekbar/EnableSlideT
public static final fun getEnableSlideToSeekPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getEnableSlideToSeekPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
} }
public final class app/revanced/patches/youtube/interaction/seekbar/HideSeekbarPatchKt {
public static final fun getHideSeekbarPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/interaction/seekbar/SeekbarPatchKt {
public static final fun getSeekbarPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/youtube/interaction/seekbar/SeekbarThumbnailsPatchKt { public final class app/revanced/patches/youtube/interaction/seekbar/SeekbarThumbnailsPatchKt {
public static final fun getSeekbarThumbnailsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getSeekbarThumbnailsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
} }
@@ -1185,17 +1197,7 @@ public final class app/revanced/patches/youtube/layout/hide/time/HideTimestampPa
} }
public final class app/revanced/patches/youtube/layout/miniplayer/MiniplayerPatchKt { public final class app/revanced/patches/youtube/layout/miniplayer/MiniplayerPatchKt {
public static final fun getFloatyBarButtonTopMargin ()J
public static final fun getMiniplayerMaxSize ()J
public static final fun getMiniplayerPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getMiniplayerPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun getModernMiniplayerClose ()J
public static final fun getModernMiniplayerExpand ()J
public static final fun getModernMiniplayerForwardButton ()J
public static final fun getModernMiniplayerRewindButton ()J
public static final fun getPlayerOverlays ()J
public static final fun getScrimOverlay ()J
public static final fun getYtOutlinePictureInPictureWhite24 ()J
public static final fun getYtOutlineXWhite24 ()J
} }
public final class app/revanced/patches/youtube/layout/panels/popup/PlayerPopupPanelsPatchKt { public final class app/revanced/patches/youtube/layout/panels/popup/PlayerPopupPanelsPatchKt {
@@ -1390,6 +1392,12 @@ public final class app/revanced/patches/youtube/misc/playservice/VersionCheckPat
public static final fun is_19_46_or_greater ()Z public static final fun is_19_46_or_greater ()Z
public static final fun is_19_47_or_greater ()Z public static final fun is_19_47_or_greater ()Z
public static final fun is_19_49_or_greater ()Z public static final fun is_19_49_or_greater ()Z
public static final fun is_20_02_or_greater ()Z
public static final fun is_20_03_or_greater ()Z
public static final fun is_20_05_or_greater ()Z
public static final fun is_20_07_or_greater ()Z
public static final fun is_20_09_or_greater ()Z
public static final fun is_20_10_or_greater ()Z
} }
public final class app/revanced/patches/youtube/misc/privacy/RemoveTrackingQueryParameterPatchKt { public final class app/revanced/patches/youtube/misc/privacy/RemoveTrackingQueryParameterPatchKt {

View File

@@ -0,0 +1,18 @@
package app.revanced.patches.angulus.ads
import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.AccessFlags
// Keywords to search for in case the method name changes:
// dailyMeasurementCount
// lastMeasurementDate
// dailyAdResetCount
// MeasurementPrefs
// This fingerprint targets a method that returns the daily measurement count.
// This method is used to determine if the user has reached the daily limit of measurements.
internal val getDailyMeasurementCountFingerprint = fingerprint {
accessFlags(AccessFlags.PRIVATE)
returns("I")
strings("dailyMeasurementCount")
}

View File

@@ -0,0 +1,14 @@
package app.revanced.patches.angulus.ads
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.util.returnEarly
@Suppress("unused")
val angulusPatch = bytecodePatch(name = "Hide ads") {
compatibleWith("com.drinkplusplus.angulus")
execute {
// Always return 0 as the daily measurement count.
getDailyMeasurementCountFingerprint.method.returnEarly()
}
}

View File

@@ -12,7 +12,7 @@ val getDeviceIdPatch = bytecodePatch(
) { ) {
dependsOn(signatureDetectionPatch) dependsOn(signatureDetectionPatch)
compatibleWith("com.microblink.photomath"("8.37.0")) compatibleWith("com.microblink.photomath")
execute { execute {
getDeviceIdFingerprint.method.replaceInstructions( getDeviceIdFingerprint.method.replaceInstructions(

View File

@@ -14,5 +14,5 @@ internal val checkSignatureFingerprint = fingerprint {
Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT, Opcode.MOVE_RESULT,
) )
strings("signatures") strings("SHA")
} }

View File

@@ -11,7 +11,7 @@ val hideUpdatePopupPatch = bytecodePatch(
) { ) {
dependsOn(signatureDetectionPatch) dependsOn(signatureDetectionPatch)
compatibleWith("com.microblink.photomath"("8.32.0")) compatibleWith("com.microblink.photomath")
execute { execute {
hideUpdatePopupFingerprint.method.addInstructions( hideUpdatePopupFingerprint.method.addInstructions(

View File

@@ -11,7 +11,7 @@ val unlockPlusPatch = bytecodePatch(
) { ) {
dependsOn(signatureDetectionPatch, enableBookpointPatch) dependsOn(signatureDetectionPatch, enableBookpointPatch)
compatibleWith("com.microblink.photomath"("8.37.0")) compatibleWith("com.microblink.photomath")
execute { execute {
isPlusUnlockedFingerprint.method.addInstructions( isPlusUnlockedFingerprint.method.addInstructions(

View File

@@ -7,6 +7,8 @@ import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.BasePreference import app.revanced.patches.shared.misc.settings.preference.BasePreference
import app.revanced.patches.shared.misc.settings.preference.IntentPreference import app.revanced.patches.shared.misc.settings.preference.IntentPreference
import app.revanced.patches.shared.misc.settings.preference.PreferenceCategory
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference
import app.revanced.util.ResourceGroup import app.revanced.util.ResourceGroup
import app.revanced.util.copyResources import app.revanced.util.copyResources
import app.revanced.util.getNode import app.revanced.util.getNode
@@ -36,14 +38,14 @@ fun settingsPatch (
execute { execute {
copyResources( copyResources(
"settings", "settings",
ResourceGroup("xml", "revanced_prefs.xml"), ResourceGroup("xml", "revanced_prefs.xml", "revanced_prefs_icons.xml"),
) )
addResources("shared", "misc.settings.settingsResourcePatch") addResources("shared", "misc.settings.settingsResourcePatch")
} }
finalize { finalize {
fun Node.addPreference(preference: BasePreference, prepend: Boolean = false) { fun Node.addPreference(preference: BasePreference) {
preference.serialize(ownerDocument) { resource -> preference.serialize(ownerDocument) { resource ->
// TODO: Currently, resources can only be added to "values", which may not be the correct place. // TODO: Currently, resources can only be added to "values", which may not be the correct place.
// It may be necessary to ask for the desired resourceValue in the future. // It may be necessary to ask for the desired resourceValue in the future.
@@ -61,7 +63,7 @@ fun settingsPatch (
val preferenceFileName = "res/xml/$fileName.xml" val preferenceFileName = "res/xml/$fileName.xml"
if (get(preferenceFileName).exists()) { if (get(preferenceFileName).exists()) {
document(preferenceFileName).use { document -> document(preferenceFileName).use { document ->
document.getNode("PreferenceScreen").addPreference(intent, true) document.getNode("PreferenceScreen").addPreference(intent)
} }
modified = true modified = true
} }
@@ -71,6 +73,30 @@ fun settingsPatch (
} }
// Add all preferences to the ReVanced fragment. // Add all preferences to the ReVanced fragment.
document("res/xml/revanced_prefs_icons.xml").use { document ->
val revancedPreferenceScreenNode = document.getNode("PreferenceScreen")
preferences.forEach { revancedPreferenceScreenNode.addPreference(it) }
}
// Because the icon preferences require declaring a layout resource,
// there is no easy way to change to the Android default preference layout
// after the preference is inflated.
// Using two different preference files is the simplest and most robust solution.
fun removeIconsAndLayout(preferences: Collection<BasePreference>) {
preferences.forEach { preference ->
preference.icon = null
preference.layout = null
if (preference is PreferenceCategory) {
removeIconsAndLayout(preference.preferences)
}
if (preference is PreferenceScreenPreference) {
removeIconsAndLayout(preference.preferences)
}
}
}
removeIconsAndLayout(preferences)
document("res/xml/revanced_prefs.xml").use { document -> document("res/xml/revanced_prefs.xml").use { document ->
val revancedPreferenceScreenNode = document.getNode("PreferenceScreen") val revancedPreferenceScreenNode = document.getNode("PreferenceScreen")
preferences.forEach { revancedPreferenceScreenNode.addPreference(it) } preferences.forEach { revancedPreferenceScreenNode.addPreference(it) }

View File

@@ -19,10 +19,17 @@ abstract class BasePreference(
val key: String? = null, val key: String? = null,
val titleKey: String? = "${key}_title", val titleKey: String? = "${key}_title",
val summaryKey: String? = "${key}_summary", val summaryKey: String? = "${key}_summary",
val icon: String? = null, icon: String? = null,
val layout: String? = null, layout: String? = null,
val tag: String val tag: String
) { ) {
var icon: String? = icon
internal set
var layout: String? = layout
internal set
/** /**
* Serialize preference element to XML. * Serialize preference element to XML.
* Overriding methods should invoke super and operate on its return value. * Overriding methods should invoke super and operate on its return value.

View File

@@ -145,7 +145,25 @@ internal val patchIncludedExtensionMethodFingerprint = fingerprint {
internal const val MEDIA_FETCH_HOT_CONFIG_FEATURE_FLAG = 45645570L internal const val MEDIA_FETCH_HOT_CONFIG_FEATURE_FLAG = 45645570L
internal val mediaFetchHotConfigFingerprint = fingerprint { internal val mediaFetchHotConfigFingerprint = fingerprint {
literal { literal { MEDIA_FETCH_HOT_CONFIG_FEATURE_FLAG }
MEDIA_FETCH_HOT_CONFIG_FEATURE_FLAG }
}
// 20.10+
internal const val MEDIA_FETCH_HOT_CONFIG_ALTERNATIVE_FEATURE_FLAG = 45683169L
internal val mediaFetchHotConfigAlternativeFingerprint = fingerprint {
literal { MEDIA_FETCH_HOT_CONFIG_ALTERNATIVE_FEATURE_FLAG }
}
// Feature flag that enables different code for parsing and starting video playback,
// but it's exact purpose is not known. If this flag is enabled while stream spoofing
// then videos will never start playback and load forever.
// Flag does not seem to affect playback if spoofing is off.
internal const val PLAYBACK_START_CHECK_ENDPOINT_USED_FEATURE_FLAG = 45665455L
internal val playbackStartDescriptorFeatureFlagFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
parameters()
returns("Z")
literal { PLAYBACK_START_CHECK_ENDPOINT_USED_FEATURE_FLAG }
} }

View File

@@ -10,6 +10,7 @@ import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.util.findFreeRegister
import app.revanced.util.findInstructionIndicesReversedOrThrow import app.revanced.util.findInstructionIndicesReversedOrThrow
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
@@ -31,7 +32,9 @@ internal const val EXTENSION_CLASS_DESCRIPTOR =
fun spoofVideoStreamsPatch( fun spoofVideoStreamsPatch(
block: BytecodePatchBuilder.() -> Unit = {}, block: BytecodePatchBuilder.() -> Unit = {},
applyMediaFetchHotConfigChanges: BytecodePatchBuilder.() -> Boolean = { false }, fixMediaFetchHotConfigChanges: BytecodePatchBuilder.() -> Boolean = { false },
fixMediaFetchHotConfigAlternativeChanges: BytecodePatchBuilder.() -> Boolean = { false },
fixParsePlaybackResponseFeatureFlag: BytecodePatchBuilder.() -> Boolean = { false },
executeBlock: BytecodePatchContext.() -> Unit = {}, executeBlock: BytecodePatchContext.() -> Unit = {},
) = bytecodePatch( ) = bytecodePatch(
name = "Spoof video streams", name = "Spoof video streams",
@@ -92,14 +95,14 @@ fun spoofVideoStreamsPatch(
getReference<MethodReference>()?.name == "newUrlRequestBuilder" getReference<MethodReference>()?.name == "newUrlRequestBuilder"
} }
val urlRegister = getInstruction<FiveRegisterInstruction>(newRequestBuilderIndex).registerD val urlRegister = getInstruction<FiveRegisterInstruction>(newRequestBuilderIndex).registerD
val freeRegister = getInstruction<OneRegisterInstruction>(newRequestBuilderIndex + 1).registerA val freeRegister = findFreeRegister(newRequestBuilderIndex, urlRegister)
addInstructions( addInstructions(
newRequestBuilderIndex, newRequestBuilderIndex,
""" """
move-object v$freeRegister, p1 move-object v$freeRegister, p1
invoke-static { v$urlRegister, v$freeRegister }, $EXTENSION_CLASS_DESCRIPTOR->fetchStreams(Ljava/lang/String;Ljava/util/Map;)V invoke-static { v$urlRegister, v$freeRegister }, $EXTENSION_CLASS_DESCRIPTOR->fetchStreams(Ljava/lang/String;Ljava/util/Map;)V
""", """
) )
} }
@@ -241,13 +244,27 @@ fun spoofVideoStreamsPatch(
// region turn off stream config replacement feature flag. // region turn off stream config replacement feature flag.
if (applyMediaFetchHotConfigChanges()) { if (fixMediaFetchHotConfigChanges()) {
mediaFetchHotConfigFingerprint.method.insertFeatureFlagBooleanOverride( mediaFetchHotConfigFingerprint.method.insertFeatureFlagBooleanOverride(
MEDIA_FETCH_HOT_CONFIG_FEATURE_FLAG, MEDIA_FETCH_HOT_CONFIG_FEATURE_FLAG,
"$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z" "$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z"
) )
} }
if (fixMediaFetchHotConfigAlternativeChanges()) {
mediaFetchHotConfigAlternativeFingerprint.method.insertFeatureFlagBooleanOverride(
MEDIA_FETCH_HOT_CONFIG_ALTERNATIVE_FEATURE_FLAG,
"$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z"
)
}
if (fixParsePlaybackResponseFeatureFlag()) {
playbackStartDescriptorFeatureFlagFingerprint.method.insertFeatureFlagBooleanOverride(
PLAYBACK_START_CHECK_ENDPOINT_USED_FEATURE_FLAG,
"$EXTENSION_CLASS_DESCRIPTOR->usePlaybackStartFeatureFlag(Z)Z"
)
}
// endregion // endregion
executeBlock() executeBlock()

View File

@@ -82,9 +82,8 @@ val hideAdsPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -29,9 +29,8 @@ val hideGetPremiumPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -27,9 +27,8 @@ val videoAdsPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -57,9 +57,8 @@ val copyVideoUrlPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -28,9 +28,8 @@ val removeViewerDiscretionDialogPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -72,9 +72,8 @@ val downloadsPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -11,8 +11,10 @@ import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.settings.settingsPatch
private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/DisablePreciseSeekingGesturePatch;"
val disablePreciseSeekingGesturePatch = bytecodePatch( val disablePreciseSeekingGesturePatch = bytecodePatch(
name = "Disable precise seeking gesture",
description = "Adds an option to disable precise seeking when swiping up on the seekbar.", description = "Adds an option to disable precise seeking when swiping up on the seekbar.",
) { ) {
dependsOn( dependsOn(
@@ -21,26 +23,12 @@ val disablePreciseSeekingGesturePatch = bytecodePatch(
addResourcesPatch, addResourcesPatch,
) )
compatibleWith(
"com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42",
"19.43.41",
"19.45.38",
"19.46.42",
"19.47.53",
),
)
execute { execute {
addResources("youtube", "interaction.seekbar.disablePreciseSeekingGesturePatch") addResources("youtube", "interaction.seekbar.disablePreciseSeekingGesturePatch")
PreferenceScreen.SEEKBAR.addPreferences( PreferenceScreen.SEEKBAR.addPreferences(
SwitchPreference("revanced_disable_precise_seeking_gesture"), SwitchPreference("revanced_disable_precise_seeking_gesture"),
) )
val extensionMethodDescriptor =
"Lapp/revanced/extension/youtube/patches/DisablePreciseSeekingGesturePatch;"
allowSwipingUpGestureFingerprint.match( allowSwipingUpGestureFingerprint.match(
swipingUpGestureParentFingerprint.originalClassDef, swipingUpGestureParentFingerprint.originalClassDef,
@@ -48,7 +36,7 @@ val disablePreciseSeekingGesturePatch = bytecodePatch(
addInstructionsWithLabels( addInstructionsWithLabels(
0, 0,
""" """
invoke-static { }, $extensionMethodDescriptor->isGestureDisabled()Z invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->isGestureDisabled()Z
move-result v0 move-result v0
if-eqz v0, :disabled if-eqz v0, :disabled
return-void return-void
@@ -63,7 +51,7 @@ val disablePreciseSeekingGesturePatch = bytecodePatch(
addInstructionsWithLabels( addInstructionsWithLabels(
0, 0,
""" """
invoke-static { }, $extensionMethodDescriptor->isGestureDisabled()Z invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->isGestureDisabled()Z
move-result v0 move-result v0
if-eqz v0, :disabled if-eqz v0, :disabled
const/4 v0, 0x0 const/4 v0, 0x0

View File

@@ -15,7 +15,6 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference
val enableSeekbarTappingPatch = bytecodePatch( val enableSeekbarTappingPatch = bytecodePatch(
name = "Enable tap to seek",
description = "Adds an option to enable tap to seek on the seekbar of the video player.", description = "Adds an option to enable tap to seek on the seekbar of the video player.",
) { ) {
dependsOn( dependsOn(
@@ -24,18 +23,6 @@ val enableSeekbarTappingPatch = bytecodePatch(
addResourcesPatch, addResourcesPatch,
) )
compatibleWith(
"com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42",
"19.43.41",
"19.45.38",
"19.46.42",
"19.47.53",
),
)
execute { execute {
addResources("youtube", "interaction.seekbar.enableSeekbarTappingPatch") addResources("youtube", "interaction.seekbar.enableSeekbarTappingPatch")

View File

@@ -18,11 +18,9 @@ import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal const val EXTENSION_METHOD_DESCRIPTOR = private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/SlideToSeekPatch;"
"Lapp/revanced/extension/youtube/patches/SlideToSeekPatch;->isSlideToSeekDisabled(Z)Z"
val enableSlideToSeekPatch = bytecodePatch( val enableSlideToSeekPatch = bytecodePatch(
name = "Enable slide to seek",
description = "Adds an option to enable slide to seek " + description = "Adds an option to enable slide to seek " +
"instead of playing at 2x speed when pressing and holding in the video player." "instead of playing at 2x speed when pressing and holding in the video player."
) { ) {
@@ -33,18 +31,6 @@ val enableSlideToSeekPatch = bytecodePatch(
versionCheckPatch, versionCheckPatch,
) )
compatibleWith(
"com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42",
"19.43.41",
"19.45.38",
"19.46.42",
"19.47.53",
),
)
execute { execute {
addResources("youtube", "interaction.seekbar.enableSlideToSeekPatch") addResources("youtube", "interaction.seekbar.enableSlideToSeekPatch")
@@ -60,6 +46,8 @@ val enableSlideToSeekPatch = bytecodePatch(
val checkReference = slideToSeekFingerprint.method.getInstruction(checkIndex) val checkReference = slideToSeekFingerprint.method.getInstruction(checkIndex)
.getReference<MethodReference>()!! .getReference<MethodReference>()!!
val extensionMethodDescriptor = "$EXTENSION_CLASS_DESCRIPTOR->isSlideToSeekDisabled(Z)Z"
// A/B check method was only called on this class. // A/B check method was only called on this class.
slideToSeekFingerprint.classDef.methods.forEach { method -> slideToSeekFingerprint.classDef.methods.forEach { method ->
method.findInstructionIndicesReversed { method.findInstructionIndicesReversed {
@@ -71,7 +59,7 @@ val enableSlideToSeekPatch = bytecodePatch(
addInstructions( addInstructions(
index + 2, index + 2,
""" """
invoke-static { v$register }, $EXTENSION_METHOD_DESCRIPTOR invoke-static { v$register }, $extensionMethodDescriptor
move-result v$register move-result v$register
""", """,
) )
@@ -96,7 +84,7 @@ val enableSlideToSeekPatch = bytecodePatch(
addInstructions( addInstructions(
targetIndex + 1, targetIndex + 1,
""" """
invoke-static { v$targetRegister }, $EXTENSION_METHOD_DESCRIPTOR invoke-static { v$targetRegister }, $extensionMethodDescriptor
move-result v$targetRegister move-result v$targetRegister
""", """,
) )
@@ -110,7 +98,7 @@ val enableSlideToSeekPatch = bytecodePatch(
addInstructions( addInstructions(
insertIndex, insertIndex,
""" """
invoke-static { v$targetRegister }, $EXTENSION_METHOD_DESCRIPTOR invoke-static { v$targetRegister }, $extensionMethodDescriptor
move-result v$targetRegister move-result v$targetRegister
""", """,
) )

View File

@@ -0,0 +1,46 @@
package app.revanced.patches.youtube.interaction.seekbar
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.layout.seekbar.seekbarColorPatch
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.shared.seekbarFingerprint
import app.revanced.patches.youtube.shared.seekbarOnDrawFingerprint
val hideSeekbarPatch = bytecodePatch(
description = "Adds an option to hide the seekbar.",
) {
dependsOn(
sharedExtensionPatch,
settingsPatch,
seekbarColorPatch,
addResourcesPatch,
)
execute {
addResources("youtube", "layout.hide.seekbar.hideSeekbarPatch")
PreferenceScreen.SEEKBAR.addPreferences(
SwitchPreference("revanced_hide_seekbar"),
SwitchPreference("revanced_hide_seekbar_thumbnail"),
)
seekbarOnDrawFingerprint.match(seekbarFingerprint.originalClassDef).method.addInstructionsWithLabels(
0,
"""
const/4 v0, 0x0
invoke-static { }, Lapp/revanced/extension/youtube/patches/HideSeekbarPatch;->hideSeekbar()Z
move-result v0
if-eqz v0, :hide_seekbar
return-void
:hide_seekbar
nop
""",
)
}
}

View File

@@ -0,0 +1,31 @@
package app.revanced.patches.youtube.interaction.seekbar
import app.revanced.patcher.patch.bytecodePatch
@Suppress("unused")
val seekbarPatch = bytecodePatch(
name = "Seekbar",
description = "Adds options to disable precise seeking when swiping up on the seekbar, " +
"slide to seek instead of playing at 2x speed when pressing and holding, " +
"tapping the player seekbar to seek, " +
"and hiding the video player seekbar."
) {
dependsOn(
disablePreciseSeekingGesturePatch,
enableSlideToSeekPatch,
enableSeekbarTappingPatch,
hideSeekbarPatch,
seekbarThumbnailsPatch
)
compatibleWith(
"com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42",
"19.43.41",
"19.47.53",
"20.07.39",
)
)
}

View File

@@ -10,6 +10,7 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.layout.seekbar.fullscreenSeekbarThumbnailsFingerprint import app.revanced.patches.youtube.layout.seekbar.fullscreenSeekbarThumbnailsFingerprint
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.playservice.is_19_17_or_greater import app.revanced.patches.youtube.misc.playservice.is_19_17_or_greater
import app.revanced.patches.youtube.misc.playservice.is_20_09_or_greater
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.PreferenceScreen
@@ -17,7 +18,6 @@ private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/SeekbarThumbnailsPatch;" "Lapp/revanced/extension/youtube/patches/SeekbarThumbnailsPatch;"
val seekbarThumbnailsPatch = bytecodePatch( val seekbarThumbnailsPatch = bytecodePatch(
name = "Seekbar thumbnails",
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.", "Patching 19.16.39 adds an option to restore old seekbar thumbnails.",
) { ) {
@@ -27,19 +27,13 @@ val seekbarThumbnailsPatch = bytecodePatch(
versionCheckPatch, versionCheckPatch,
) )
compatibleWith(
"com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42",
"19.43.41",
"19.45.38",
"19.46.42",
"19.47.53",
)
)
execute { execute {
if (is_20_09_or_greater) {
// High quality seekbar thumbnails is partially broken in 20.09
// and the code is completely removed in 20.10+
return@execute
}
addResources("youtube", "layout.seekbar.seekbarThumbnailsPatch") addResources("youtube", "layout.seekbar.seekbarThumbnailsPatch")
if (is_19_17_or_greater) { if (is_19_17_or_greater) {

View File

@@ -84,9 +84,8 @@ val swipeControlsPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -26,9 +26,8 @@ val autoCaptionsPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -47,9 +47,8 @@ val customBrandingPatch = resourcePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -45,9 +45,8 @@ val changeHeaderPatch = resourcePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
) )
) )

View File

@@ -26,9 +26,8 @@ val hideButtonsPatch = resourcePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -44,9 +44,8 @@ val navigationButtonsPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -58,9 +58,8 @@ val hidePlayerOverlayButtonsPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -37,9 +37,8 @@ val changeFormFactorPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -63,9 +63,8 @@ val hideEndscreenCardsPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -35,9 +35,8 @@ val hideEndScreenSuggestedVideoPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -33,9 +33,8 @@ val disableFullscreenAmbientModePatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -15,7 +15,21 @@ internal val hideShowMoreButtonFingerprint = fingerprint {
literal { expandButtonDownId } literal { expandButtonDownId }
} }
/**
* 20.07+
*/
internal val parseElementFromBufferFingerprint = fingerprint { internal val parseElementFromBufferFingerprint = fingerprint {
parameters("L", "L", "[B", "L", "L")
opcodes(
Opcode.IGET_OBJECT,
Opcode.IGET_BOOLEAN,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
)
strings("Failed to parse Element") // String is a partial match.
}
internal val parseElementFromBufferLegacyFingerprint = fingerprint {
parameters("L", "L", "[B", "L", "L") parameters("L", "L", "[B", "L", "L")
opcodes( opcodes(
Opcode.IGET_OBJECT, Opcode.IGET_OBJECT,
@@ -110,7 +124,6 @@ internal val showFloatingMicrophoneButtonFingerprint = fingerprint {
opcodes( opcodes(
Opcode.IGET_BOOLEAN, Opcode.IGET_BOOLEAN,
Opcode.IF_EQZ, Opcode.IF_EQZ,
Opcode.RETURN_VOID,
) )
literal { fabButtonId } literal { fabButtonId }
} }

View File

@@ -20,12 +20,14 @@ import app.revanced.patches.shared.misc.settings.preference.*
import app.revanced.patches.youtube.misc.litho.filter.addLithoFilter import app.revanced.patches.youtube.misc.litho.filter.addLithoFilter
import app.revanced.patches.youtube.misc.litho.filter.lithoFilterPatch import app.revanced.patches.youtube.misc.litho.filter.lithoFilterPatch
import app.revanced.patches.youtube.misc.navigation.navigationBarHookPatch import app.revanced.patches.youtube.misc.navigation.navigationBarHookPatch
import app.revanced.patches.youtube.misc.playservice.is_19_47_or_greater import app.revanced.patches.youtube.misc.playservice.is_20_07_or_greater
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.util.findFreeRegister
import app.revanced.util.findInstructionIndicesReversedOrThrow import app.revanced.util.findInstructionIndicesReversedOrThrow
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@@ -120,7 +122,6 @@ val hideLayoutComponentsPatch = bytecodePatch(
addResourcesPatch, addResourcesPatch,
hideLayoutComponentsResourcePatch, hideLayoutComponentsResourcePatch,
navigationBarHookPatch, navigationBarHookPatch,
versionCheckPatch
) )
compatibleWith( compatibleWith(
@@ -132,6 +133,7 @@ val hideLayoutComponentsPatch = bytecodePatch(
"19.45.38", "19.45.38",
"19.46.42", "19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )
@@ -247,29 +249,31 @@ val hideLayoutComponentsPatch = bytecodePatch(
// region Mix playlists // region Mix playlists
parseElementFromBufferFingerprint.method.apply { (if (is_20_07_or_greater) parseElementFromBufferFingerprint
val startIndex = parseElementFromBufferFingerprint.patternMatch!!.startIndex else parseElementFromBufferLegacyFingerprint).let {
// Target code is a mess with a lot of register moves. it.method.apply {
// There is no simple way to find a free register for all versions so this is hard coded. val byteArrayParameter = "p3"
val freeRegister = if (is_19_47_or_greater) 6 else 0 val startIndex = it.patternMatch!!.startIndex
val byteArrayParameter = "p3" val conversionContextRegister = getInstruction<TwoRegisterInstruction>(startIndex).registerA
val conversionContextRegister = getInstruction<TwoRegisterInstruction>(startIndex).registerA val returnEmptyComponentInstruction = instructions.last { it.opcode == Opcode.INVOKE_STATIC }
val returnEmptyComponentInstruction = instructions.last { it.opcode == Opcode.INVOKE_STATIC } val returnEmptyComponentRegister = (returnEmptyComponentInstruction as FiveRegisterInstruction).registerC
val returnEmptyComponentRegister = (returnEmptyComponentInstruction as FiveRegisterInstruction).registerC val insertIndex = startIndex + 1
val freeRegister = findFreeRegister(insertIndex, conversionContextRegister, returnEmptyComponentRegister)
addInstructionsWithLabels( addInstructionsWithLabels(
startIndex + 1, insertIndex,
""" """
invoke-static { v$conversionContextRegister, $byteArrayParameter }, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->filterMixPlaylists(Ljava/lang/Object;[B)Z invoke-static { v$conversionContextRegister, $byteArrayParameter }, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->filterMixPlaylists(Ljava/lang/Object;[B)Z
move-result v$freeRegister move-result v$freeRegister
if-eqz v$freeRegister, :show if-eqz v$freeRegister, :show
move-object v$returnEmptyComponentRegister, p1 # Required for 19.47 move-object v$returnEmptyComponentRegister, p1 # Required for 19.47
goto :return_empty_component goto :return_empty_component
:show :show
const/4 v$freeRegister, 0x0 # Restore register, required for 19.16 nop
""", """,
ExternalLabel("return_empty_component", returnEmptyComponentInstruction), ExternalLabel("return_empty_component", returnEmptyComponentInstruction),
) )
}
} }
// endregion // endregion
@@ -345,19 +349,18 @@ val hideLayoutComponentsPatch = bytecodePatch(
// region hide floating microphone // region hide floating microphone
showFloatingMicrophoneButtonFingerprint.let { showFloatingMicrophoneButtonFingerprint.method.apply {
it.method.apply { val literalIndex = indexOfFirstLiteralInstructionOrThrow(fabButtonId)
val startIndex = it.patternMatch!!.startIndex val booleanIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.IGET_BOOLEAN)
val register = getInstruction<TwoRegisterInstruction>(startIndex).registerA val register = getInstruction<TwoRegisterInstruction>(booleanIndex).registerA
addInstructions( addInstructions(
startIndex + 1, booleanIndex + 1,
""" """
invoke-static { v$register }, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->hideFloatingMicrophoneButton(Z)Z invoke-static { v$register }, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->hideFloatingMicrophoneButton(Z)Z
move-result v$register move-result v$register
""", """
) )
}
} }
// endregion // endregion

View File

@@ -61,9 +61,8 @@ val hideInfoCardsPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -28,9 +28,8 @@ val hidePlayerFlyoutMenuPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -33,9 +33,8 @@ val disableRollingNumberAnimationPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -1,59 +1,11 @@
package app.revanced.patches.youtube.layout.hide.seekbar package app.revanced.patches.youtube.layout.hide.seekbar
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.youtube.interaction.seekbar.hideSeekbarPatch
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.layout.seekbar.seekbarColorPatch
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.shared.seekbarFingerprint
import app.revanced.patches.youtube.shared.seekbarOnDrawFingerprint
val hideSeekbarPatch = bytecodePatch( @Deprecated("Patch was moved to app.revanced.patches.youtube.interaction.seekbar")
name = "Hide seekbar", val hideSeekbarPatch = bytecodePatch {
description = "Adds an option to hide the seekbar.",
) {
dependsOn( dependsOn(
sharedExtensionPatch, hideSeekbarPatch
settingsPatch,
seekbarColorPatch,
addResourcesPatch,
) )
compatibleWith(
"com.google.android.youtube"(
"19.16.39",
"19.25.37",
"19.34.42",
"19.43.41",
"19.45.38",
"19.46.42",
"19.47.53",
),
)
execute {
addResources("youtube", "layout.hide.seekbar.hideSeekbarPatch")
PreferenceScreen.SEEKBAR.addPreferences(
SwitchPreference("revanced_hide_seekbar"),
SwitchPreference("revanced_hide_seekbar_thumbnail"),
)
seekbarOnDrawFingerprint.match(seekbarFingerprint.originalClassDef).method.addInstructionsWithLabels(
0,
"""
const/4 v0, 0x0
invoke-static { }, Lapp/revanced/extension/youtube/patches/HideSeekbarPatch;->hideSeekbar()Z
move-result v0
if-eqz v0, :hide_seekbar
return-void
:hide_seekbar
nop
""",
)
}
} }

View File

@@ -176,9 +176,8 @@ val hideShortsComponentsPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -25,9 +25,8 @@ val hideTimestampPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -30,7 +30,7 @@ internal val miniplayerModernAddViewListenerFingerprint = fingerprint {
internal val miniplayerModernCloseButtonFingerprint = fingerprint { internal val miniplayerModernCloseButtonFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("Landroid/widget/ImageView;") returns("L")
parameters() parameters()
literal { modernMiniplayerClose } literal { modernMiniplayerClose }
} }
@@ -62,7 +62,7 @@ internal val miniplayerOnCloseHandlerFingerprint = fingerprint {
*/ */
internal val miniplayerModernExpandButtonFingerprint = fingerprint { internal val miniplayerModernExpandButtonFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("Landroid/widget/ImageView;") returns("L")
parameters() parameters()
literal { modernMiniplayerExpand } literal { modernMiniplayerExpand }
} }
@@ -82,7 +82,7 @@ internal val miniplayerModernExpandCloseDrawablesFingerprint = fingerprint {
*/ */
internal val miniplayerModernForwardButtonFingerprint = fingerprint { internal val miniplayerModernForwardButtonFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("Landroid/widget/ImageView;") returns("L")
parameters() parameters()
literal { modernMiniplayerForwardButton } literal { modernMiniplayerForwardButton }
} }
@@ -92,7 +92,6 @@ internal val miniplayerModernForwardButtonFingerprint = fingerprint {
*/ */
internal val miniplayerModernOverlayViewFingerprint = fingerprint { internal val miniplayerModernOverlayViewFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("V")
parameters() parameters()
literal { scrimOverlay } literal { scrimOverlay }
} }
@@ -102,7 +101,7 @@ internal val miniplayerModernOverlayViewFingerprint = fingerprint {
*/ */
internal val miniplayerModernRewindButtonFingerprint = fingerprint { internal val miniplayerModernRewindButtonFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("Landroid/widget/ImageView;") returns("L")
parameters() parameters()
literal { modernMiniplayerRewindButton } literal { modernMiniplayerRewindButton }
} }
@@ -114,6 +113,13 @@ internal val miniplayerModernViewParentFingerprint = fingerprint {
strings("player_overlay_modern_mini_player_controls") strings("player_overlay_modern_mini_player_controls")
} }
internal val miniplayerModernActionButtonFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("L")
parameters()
literal { modernMiniPlayerOverlayActionButton }
}
internal val miniplayerMinimumSizeFingerprint = fingerprint { internal val miniplayerMinimumSizeFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
custom { method, _ -> custom { method, _ ->

View File

@@ -34,27 +34,29 @@ import com.android.tools.smali.dexlib2.iface.reference.TypeReference
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
var floatyBarButtonTopMargin = -1L internal var floatyBarButtonTopMargin = -1L
private set private set
// Only available in 19.15 and upwards. // Only available in 19.15 and upwards.
var ytOutlineXWhite24 = -1L internal var ytOutlineXWhite24 = -1L
private set private set
var ytOutlinePictureInPictureWhite24 = -1L internal var ytOutlinePictureInPictureWhite24 = -1L
private set private set
var scrimOverlay = -1L internal var scrimOverlay = -1L
private set private set
var modernMiniplayerClose = -1L internal var modernMiniplayerClose = -1L
private set private set
var modernMiniplayerExpand = -1L internal var modernMiniplayerExpand = -1L
private set private set
var modernMiniplayerRewindButton = -1L internal var modernMiniplayerRewindButton = -1L
private set private set
var modernMiniplayerForwardButton = -1L internal var modernMiniplayerForwardButton = -1L
private set private set
var playerOverlays = -1L internal var modernMiniPlayerOverlayActionButton = -1L
private set private set
var miniplayerMaxSize = -1L internal var playerOverlays = -1L
private set
internal var miniplayerMaxSize = -1L
private set private set
private val miniplayerResourcePatch = resourcePatch { private val miniplayerResourcePatch = resourcePatch {
@@ -100,6 +102,11 @@ private val miniplayerResourcePatch = resourcePatch {
"modern_miniplayer_forward_button", "modern_miniplayer_forward_button",
] ]
modernMiniPlayerOverlayActionButton = resourceMappings[
"id",
"modern_miniplayer_overlay_action_button"
]
// Resource id is not used during patching, but is used by extension. // Resource id is not used during patching, but is used by extension.
// Verify the resource is present while patching. // Verify the resource is present while patching.
resourceMappings[ resourceMappings[
@@ -167,6 +174,7 @@ val miniplayerPatch = bytecodePatch(
"19.45.38", "19.45.38",
"19.46.42", "19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )
@@ -175,19 +183,25 @@ val miniplayerPatch = bytecodePatch(
val preferences = mutableSetOf<BasePreference>() val preferences = mutableSetOf<BasePreference>()
preferences += preferences +=
if (is_19_43_or_greater) { if (is_20_03_or_greater) {
ListPreference( ListPreference(
"revanced_miniplayer_type", "revanced_miniplayer_type",
summaryKey = null, summaryKey = null,
) )
} else if (is_19_43_or_greater) {
ListPreference(
"revanced_miniplayer_type",
summaryKey = null,
entriesKey = "revanced_miniplayer_type_legacy_19_43_entries",
entryValuesKey = "revanced_miniplayer_type_legacy_19_43_entry_values",
)
} else { } else {
ListPreference( ListPreference(
"revanced_miniplayer_type", "revanced_miniplayer_type",
summaryKey = null, summaryKey = null,
entriesKey = "revanced_miniplayer_type_legacy_entries", entriesKey = "revanced_miniplayer_type_legacy_19_16_entries",
entryValuesKey = "revanced_miniplayer_type_legacy_entry_values", entryValuesKey = "revanced_miniplayer_type_legacy_19_16_entry_values",
) )
} }
@@ -209,13 +223,13 @@ val miniplayerPatch = bytecodePatch(
preferences += SwitchPreference("revanced_miniplayer_hide_subtext") preferences += SwitchPreference("revanced_miniplayer_hide_subtext")
preferences += if (is_19_26_or_greater) { preferences += if (is_19_26_or_greater) {
SwitchPreference("revanced_miniplayer_hide_expand_close") SwitchPreference("revanced_miniplayer_hide_overlay_buttons")
} else { } else {
SwitchPreference( SwitchPreference(
key = "revanced_miniplayer_hide_expand_close", key = "revanced_miniplayer_hide_overlay_buttons",
titleKey = "revanced_miniplayer_hide_expand_close_legacy_title", titleKey = "revanced_miniplayer_hide_overlay_buttons_legacy_title",
summaryOnKey = "revanced_miniplayer_hide_expand_close_legacy_summary_on", summaryOnKey = "revanced_miniplayer_hide_overlay_buttons_legacy_summary_on",
summaryOffKey = "revanced_miniplayer_hide_expand_close_legacy_summary_off", summaryOffKey = "revanced_miniplayer_hide_overlay_buttons_legacy_summary_off",
) )
} }
@@ -365,7 +379,7 @@ val miniplayerPatch = bytecodePatch(
if (is_19_23_or_greater) { if (is_19_23_or_greater) {
miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride( miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride(
MINIPLAYER_DRAG_DROP_FEATURE_KEY, MINIPLAYER_DRAG_DROP_FEATURE_KEY,
"enableMiniplayerDragAndDrop", "getMiniplayerDragAndDrop",
) )
} }
@@ -382,7 +396,7 @@ val miniplayerPatch = bytecodePatch(
miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride( miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride(
MINIPLAYER_DOUBLE_TAP_FEATURE_KEY, MINIPLAYER_DOUBLE_TAP_FEATURE_KEY,
"enableMiniplayerDoubleTapAction", "getMiniplayerDoubleTapAction",
) )
} }
@@ -398,7 +412,7 @@ val miniplayerPatch = bytecodePatch(
addInstructions( addInstructions(
targetIndex + 1, targetIndex + 1,
""" """
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->setMiniplayerDefaultSize(I)I invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getMiniplayerDefaultSize(I)I
move-result v$register move-result v$register
""", """,
) )
@@ -421,7 +435,7 @@ val miniplayerPatch = bytecodePatch(
if (is_19_36_or_greater) { if (is_19_36_or_greater) {
miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride( miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride(
MINIPLAYER_ROUNDED_CORNERS_FEATURE_KEY, MINIPLAYER_ROUNDED_CORNERS_FEATURE_KEY,
"setRoundedCorners", "getRoundedCorners",
) )
} }
@@ -433,7 +447,7 @@ val miniplayerPatch = bytecodePatch(
miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride( miniplayerModernConstructorFingerprint.insertMiniplayerFeatureFlagBooleanOverride(
MINIPLAYER_HORIZONTAL_DRAG_FEATURE_KEY, MINIPLAYER_HORIZONTAL_DRAG_FEATURE_KEY,
"setHorizontalDrag", "getHorizontalDrag",
) )
} }
@@ -473,6 +487,11 @@ val miniplayerPatch = bytecodePatch(
modernMiniplayerClose, modernMiniplayerClose,
"hideMiniplayerExpandClose", "hideMiniplayerExpandClose",
), ),
Triple(
miniplayerModernActionButtonFingerprint,
modernMiniPlayerOverlayActionButton,
"hideMiniplayerActionButton"
),
Triple( Triple(
miniplayerModernRewindButtonFingerprint, miniplayerModernRewindButtonFingerprint,
modernMiniplayerRewindButton, modernMiniplayerRewindButton,
@@ -490,12 +509,25 @@ val miniplayerPatch = bytecodePatch(
), ),
).forEach { (fingerprint, literalValue, methodName) -> ).forEach { (fingerprint, literalValue, methodName) ->
fingerprint.match( fingerprint.match(
miniplayerModernViewParentFingerprint.classDef, miniplayerModernViewParentFingerprint.originalClassDef
).method.hookInflatedView( ).method.apply {
literalValue, val literalIndex = indexOfFirstLiteralInstructionOrThrow(literalValue)
"Landroid/widget/ImageView;", val checkCastIndex = indexOfFirstInstruction(literalIndex) {
"$EXTENSION_CLASS_DESCRIPTOR->$methodName(Landroid/widget/ImageView;)V", opcode == Opcode.CHECK_CAST &&
) getReference<TypeReference>()?.type == "Landroid/widget/ImageView;"
}
val viewIndex = if (checkCastIndex >= 0) {
checkCastIndex
} else {
indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT_OBJECT)
}
val viewRegister = getInstruction<OneRegisterInstruction>(viewIndex).registerA
addInstruction(
viewIndex + 1,
"invoke-static { v$viewRegister }, $EXTENSION_CLASS_DESCRIPTOR->$methodName(Landroid/view/View;)V"
)
}
} }
miniplayerModernAddViewListenerFingerprint.match( miniplayerModernAddViewListenerFingerprint.match(
@@ -510,33 +542,40 @@ val miniplayerPatch = bytecodePatch(
// Modern 2 uses the same overlay controls as the regular video player, // Modern 2 uses the same overlay controls as the regular video player,
// and the overlay views are added at runtime. // and the overlay views are added at runtime.
// Add a hook to the overlay class, and pass the added views to extension. // Add a hook to the overlay class, and pass the added views to extension.
// Problem is fixed in 19.21+
// //
// NOTE: Modern 2 uses the same video UI as the regular player except resized to smaller. // NOTE: Modern 2 uses the same video UI as the regular player except resized to smaller.
// This patch code could be used to hide other player overlays that do not use Litho. // This patch code could be used to hide other player overlays that do not use Litho.
playerOverlaysLayoutFingerprint.classDef.methods.add( if (!is_19_17_or_greater) {
ImmutableMethod( playerOverlaysLayoutFingerprint.classDef.methods.add(
YOUTUBE_PLAYER_OVERLAYS_LAYOUT_CLASS_NAME, ImmutableMethod(
"addView", YOUTUBE_PLAYER_OVERLAYS_LAYOUT_CLASS_NAME,
listOf( "addView",
ImmutableMethodParameter("Landroid/view/View;", null, null), listOf(
ImmutableMethodParameter("I", null, null), ImmutableMethodParameter("Landroid/view/View;", null, null),
ImmutableMethodParameter("Landroid/view/ViewGroup\$LayoutParams;", null, null), ImmutableMethodParameter("I", null, null),
), ImmutableMethodParameter(
"V", "Landroid/view/ViewGroup\$LayoutParams;",
AccessFlags.PUBLIC.value, null,
null, null
null, ),
MutableMethodImplementation(4), ),
).toMutable().apply { "V",
addInstructions( AccessFlags.PUBLIC.value,
""" null,
invoke-super { p0, p1, p2, p3 }, Landroid/view/ViewGroup;->addView(Landroid/view/View;ILandroid/view/ViewGroup${'$'}LayoutParams;)V null,
invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->playerOverlayGroupCreated(Landroid/view/View;)V MutableMethodImplementation(4),
return-void ).toMutable().apply {
""" addInstructions(
) """
} invoke-super { p0, p1, p2, p3 }, Landroid/view/ViewGroup;->addView(Landroid/view/View;ILandroid/view/ViewGroup${'$'}LayoutParams;)V
) invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->playerOverlayGroupCreated(Landroid/view/View;)V
return-void
"""
)
}
)
}
// endregion // endregion
} }

View File

@@ -25,9 +25,8 @@ val playerPopupPanelsPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -16,9 +16,8 @@ val playerControlsBackgroundPatch = resourcePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -25,9 +25,8 @@ internal val exitFullscreenPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
) )
) )

View File

@@ -27,6 +27,7 @@ val openVideosFullscreenPatch = bytecodePatch(
"com.google.android.youtube"( "com.google.android.youtube"(
"19.46.42", "19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
) )
) )

View File

@@ -56,9 +56,8 @@ val customPlayerOverlayOpacityPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -12,6 +12,7 @@ import app.revanced.patches.youtube.misc.litho.filter.addLithoFilter
import app.revanced.patches.youtube.misc.litho.filter.lithoFilterPatch import app.revanced.patches.youtube.misc.litho.filter.lithoFilterPatch
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
import app.revanced.patches.youtube.misc.playservice.is_19_33_or_greater import app.revanced.patches.youtube.misc.playservice.is_19_33_or_greater
import app.revanced.patches.youtube.misc.playservice.is_20_10_or_greater
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.settings.addSettingPreference import app.revanced.patches.youtube.misc.settings.addSettingPreference
import app.revanced.patches.youtube.misc.settings.newIntent import app.revanced.patches.youtube.misc.settings.newIntent
@@ -56,9 +57,8 @@ val returnYouTubeDislikePatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )
@@ -70,6 +70,8 @@ val returnYouTubeDislikePatch = bytecodePatch(
key = "revanced_settings_screen_09", key = "revanced_settings_screen_09",
titleKey = "revanced_ryd_settings_title", titleKey = "revanced_ryd_settings_title",
summaryKey = null, summaryKey = null,
icon = "@drawable/revanced_settings_screen_09_ryd",
layout = "@layout/preference_with_icon",
intent = newIntent("revanced_ryd_settings_intent"), intent = newIntent("revanced_ryd_settings_intent"),
), ),
) )
@@ -121,7 +123,7 @@ val returnYouTubeDislikePatch = bytecodePatch(
val tempRegister: Int val tempRegister: Int
val charSequenceRegister: Int val charSequenceRegister: Int
if (is_19_33_or_greater) { if (is_19_33_or_greater && !is_20_10_or_greater) {
insertIndex = indexOfFirstInstructionOrThrow { insertIndex = indexOfFirstInstructionOrThrow {
(opcode == Opcode.INVOKE_STATIC || opcode == Opcode.INVOKE_STATIC_RANGE) (opcode == Opcode.INVOKE_STATIC || opcode == Opcode.INVOKE_STATIC_RANGE)
&& getReference<MethodReference>()?.returnType == textDataClassType && getReference<MethodReference>()?.returnType == textDataClassType
@@ -179,9 +181,6 @@ val returnYouTubeDislikePatch = bytecodePatch(
// region Hook rolling numbers. // region Hook rolling numbers.
// Do this last to allow patching old unsupported versions (if the user really wants),
// On older unsupported version this will fail to match and throw an exception,
// but everything will still work correctly anyway.
val dislikesIndex = rollingNumberSetterFingerprint.patternMatch!!.endIndex val dislikesIndex = rollingNumberSetterFingerprint.patternMatch!!.endIndex
rollingNumberSetterFingerprint.method.apply { rollingNumberSetterFingerprint.method.apply {

View File

@@ -33,9 +33,8 @@ val wideSearchbarPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -37,12 +37,25 @@ internal val shortsSeekbarColorFingerprint = fingerprint {
literal { reelTimeBarPlayedColorId } literal { reelTimeBarPlayedColorId }
} }
internal val playerSeekbarHandleColorFingerprint = fingerprint { internal val playerSeekbarHandle1ColorFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
parameters("Landroid/content/Context;") parameters("Landroid/content/Context;")
literal { ytStaticBrandRedId } custom { method, _ ->
method.containsLiteralInstruction(ytTextSecondaryId) &&
method.containsLiteralInstruction(ytStaticBrandRedId)
}
} }
internal val playerSeekbarHandle2ColorFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
parameters("Landroid/content/Context;")
custom { method, _ ->
method.containsLiteralInstruction(inlineTimeBarLiveSeekableRangeId) &&
method.containsLiteralInstruction(ytStaticBrandRedId)
}
}
internal val watchHistoryMenuUseProgressDrawableFingerprint = fingerprint { internal val watchHistoryMenuUseProgressDrawableFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("V") returns("V")

View File

@@ -53,6 +53,10 @@ internal var ytYoutubeMagentaColorId = -1L
private set private set
internal var ytStaticBrandRedId = -1L internal var ytStaticBrandRedId = -1L
private set private set
internal var ytTextSecondaryId = -1L
private set
internal var inlineTimeBarLiveSeekableRangeId = -1L
private set
internal const val splashSeekbarColorAttributeName = "splash_custom_seekbar_color" internal const val splashSeekbarColorAttributeName = "splash_custom_seekbar_color"
@@ -76,6 +80,18 @@ private val seekbarColorResourcePatch = resourcePatch {
"color", "color",
"inline_time_bar_played_not_highlighted_color", "inline_time_bar_played_not_highlighted_color",
] ]
ytStaticBrandRedId = resourceMappings[
"attr",
"ytStaticBrandRed"
]
ytTextSecondaryId = resourceMappings[
"attr",
"ytTextSecondary"
]
inlineTimeBarLiveSeekableRangeId = resourceMappings[
"color",
"inline_time_bar_live_seekable_range"
]
// Modify the resume playback drawable and replace the progress bar with a custom drawable. // Modify the resume playback drawable and replace the progress bar with a custom drawable.
document("res/drawable/resume_playback_progressbar_drawable.xml").use { document -> document("res/drawable/resume_playback_progressbar_drawable.xml").use { document ->
@@ -211,7 +227,7 @@ val seekbarColorPatch = bytecodePatch(
) )
execute { execute {
fun MutableMethod.addColorChangeInstructions(resourceId: Long, methodName: String) { fun MutableMethod.addColorChangeInstructions(resourceId: Long) {
val index = indexOfFirstLiteralInstructionOrThrow(resourceId) val index = indexOfFirstLiteralInstructionOrThrow(resourceId)
val insertIndex = indexOfFirstInstructionOrThrow(index, Opcode.MOVE_RESULT) val insertIndex = indexOfFirstInstructionOrThrow(index, Opcode.MOVE_RESULT)
val register = getInstruction<OneRegisterInstruction>(insertIndex).registerA val register = getInstruction<OneRegisterInstruction>(insertIndex).registerA
@@ -219,19 +235,19 @@ val seekbarColorPatch = bytecodePatch(
addInstructions( addInstructions(
insertIndex + 1, insertIndex + 1,
""" """
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->$methodName(I)I invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getVideoPlayerSeekbarColor(I)I
move-result v$register move-result v$register
""" """
) )
} }
playerSeekbarColorFingerprint.method.apply { playerSeekbarColorFingerprint.method.apply {
addColorChangeInstructions(inlineTimeBarColorizedBarPlayedColorDarkId, "getVideoPlayerSeekbarColor") addColorChangeInstructions(inlineTimeBarColorizedBarPlayedColorDarkId)
addColorChangeInstructions(inlineTimeBarPlayedNotHighlightedColorId, "getVideoPlayerSeekbarColor") addColorChangeInstructions(inlineTimeBarPlayedNotHighlightedColorId)
} }
shortsSeekbarColorFingerprint.method.apply { shortsSeekbarColorFingerprint.method.apply {
addColorChangeInstructions(reelTimeBarPlayedColorId, "getVideoPlayerSeekbarColor") addColorChangeInstructions(reelTimeBarPlayedColorId)
} }
setSeekbarClickedColorFingerprint.originalMethod.let { setSeekbarClickedColorFingerprint.originalMethod.let {
@@ -257,8 +273,11 @@ val seekbarColorPatch = bytecodePatch(
// 19.25+ changes // 19.25+ changes
playerSeekbarHandleColorFingerprint.method.apply { arrayOf(
addColorChangeInstructions(ytStaticBrandRedId, "getVideoPlayerSeekbarColor") playerSeekbarHandle1ColorFingerprint,
playerSeekbarHandle2ColorFingerprint
).forEach {
it.method.addColorChangeInstructions(ytStaticBrandRedId)
} }
// If hiding feed seekbar thumbnails, then turn off the cairo gradient // If hiding feed seekbar thumbnails, then turn off the cairo gradient

View File

@@ -37,9 +37,8 @@ val shortsAutoplayPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -16,9 +16,9 @@ import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
import app.revanced.util.findFreeRegister
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@@ -45,9 +45,8 @@ val openShortsInRegularPlayerPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )
@@ -107,11 +106,12 @@ val openShortsInRegularPlayerPatch = bytecodePatch(
getReference<MethodReference>()?.returnType == getReference<MethodReference>()?.returnType ==
"Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;" "Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;"
} }
val freeRegister = getInstruction<FiveRegisterInstruction>(index).registerC
val playbackStartRegister = getInstruction<OneRegisterInstruction>(index + 1).registerA val playbackStartRegister = getInstruction<OneRegisterInstruction>(index + 1).registerA
val insertIndex = index + 2
val freeRegister = findFreeRegister(insertIndex, playbackStartRegister)
addInstructionsWithLabels( addInstructionsWithLabels(
index + 2, insertIndex,
extensionInstructions(playbackStartRegister, freeRegister) extensionInstructions(playbackStartRegister, freeRegister)
) )
} }

View File

@@ -48,6 +48,8 @@ private val sponsorBlockResourcePatch = resourcePatch {
key = "revanced_settings_screen_10", key = "revanced_settings_screen_10",
titleKey = "revanced_sb_settings_title", titleKey = "revanced_sb_settings_title",
summaryKey = null, summaryKey = null,
icon = "@drawable/revanced_settings_screen_10_sb",
layout = "@layout/preference_with_icon",
intent = newIntent("revanced_sb_settings_intent"), intent = newIntent("revanced_sb_settings_intent"),
), ),
) )
@@ -110,9 +112,8 @@ val sponsorBlockPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -62,9 +62,8 @@ val spoofAppVersionPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -33,9 +33,8 @@ val changeStartPagePatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -7,11 +7,14 @@ import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.playservice.is_20_02_or_greater
import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.util.addInstructionsAtControlFlowLabel import app.revanced.util.addInstructionsAtControlFlowLabel
import app.revanced.util.findFreeRegister
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@@ -38,6 +41,7 @@ val disableResumingShortsOnStartupPatch = bytecodePatch(
"19.45.38", "19.45.38",
"19.46.42", "19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )
@@ -48,25 +52,47 @@ val disableResumingShortsOnStartupPatch = bytecodePatch(
SwitchPreference("revanced_disable_resuming_shorts_player"), SwitchPreference("revanced_disable_resuming_shorts_player"),
) )
userWasInShortsFingerprint.method.apply { if (is_20_02_or_greater) {
val listenableInstructionIndex = indexOfFirstInstructionOrThrow { userWasInShortsAlternativeFingerprint.let {
opcode == Opcode.INVOKE_INTERFACE && it.method.apply {
getReference<MethodReference>()?.definingClass == "Lcom/google/common/util/concurrent/ListenableFuture;" && val stringIndex = it.stringMatches!!.first().index
getReference<MethodReference>()?.name == "isDone" val booleanValueIndex = indexOfFirstInstructionReversedOrThrow(stringIndex) {
} opcode == Opcode.INVOKE_VIRTUAL &&
val freeRegister = getInstruction<OneRegisterInstruction>(listenableInstructionIndex + 1).registerA getReference<MethodReference>()?.name == "booleanValue"
}
val booleanValueRegister =
getInstruction<OneRegisterInstruction>(booleanValueIndex + 1).registerA
addInstructionsAtControlFlowLabel( addInstructions(
listenableInstructionIndex, booleanValueIndex + 2, """
""" invoke-static {v$booleanValueRegister}, $EXTENSION_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer(Z)Z
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z move-result v$booleanValueRegister
move-result v$freeRegister """
if-eqz v$freeRegister, :show_startup_shorts_player )
return-void }
:show_startup_shorts_player }
nop } else {
""", userWasInShortsLegacyFingerprint.method.apply {
) val listenableInstructionIndex = indexOfFirstInstructionOrThrow {
val reference = getReference<MethodReference>()
opcode == Opcode.INVOKE_INTERFACE &&
reference?.definingClass == "Lcom/google/common/util/concurrent/ListenableFuture;" &&
reference.name == "isDone"
}
val freeRegister = findFreeRegister(listenableInstructionIndex)
addInstructionsAtControlFlowLabel(
listenableInstructionIndex,
"""
invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z
move-result v$freeRegister
if-eqz v$freeRegister, :show
return-void
:show
nop
"""
)
}
} }
userWasInShortsConfigFingerprint.method.addInstructions( userWasInShortsConfigFingerprint.method.addInstructions(

View File

@@ -4,7 +4,17 @@ import app.revanced.patcher.fingerprint
import app.revanced.util.literal import app.revanced.util.literal
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
internal val userWasInShortsFingerprint = fingerprint { /**
* YouTube 20.02.08 ~
*/
internal val userWasInShortsAlternativeFingerprint = fingerprint {
returns("V")
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
parameters("Ljava/lang/Object;")
strings("userIsInShorts: ")
}
internal val userWasInShortsLegacyFingerprint = fingerprint {
returns("V") returns("V")
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
parameters("Ljava/lang/Object;") parameters("Ljava/lang/Object;")

View File

@@ -221,9 +221,8 @@ val themePatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -37,9 +37,8 @@ val alternativeThumbnailsPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -31,9 +31,8 @@ val bypassImageRegionRestrictionsPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -27,9 +27,8 @@ val announcementsPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -28,9 +28,8 @@ val autoRepeatPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -52,9 +52,8 @@ val backgroundPlaybackPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -38,9 +38,8 @@ val enableDebuggingPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -28,9 +28,8 @@ val spoofDeviceDimensionsPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -25,9 +25,8 @@ val checkWatchHistoryDomainNameResolutionPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -8,6 +8,7 @@ import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.util.findFreeRegister
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@@ -42,13 +43,14 @@ val fixPlaybackSpeedWhilePlayingPatch = bytecodePatch{
} }
playbackSpeedInFeedsFingerprint.method.apply { playbackSpeedInFeedsFingerprint.method.apply {
val freeRegister = implementation!!.registerCount - parameters.size - 2
val playbackSpeedIndex = indexOfGetPlaybackSpeedInstruction(this) val playbackSpeedIndex = indexOfGetPlaybackSpeedInstruction(this)
val playbackSpeedRegister = getInstruction<TwoRegisterInstruction>(playbackSpeedIndex).registerA val playbackSpeedRegister = getInstruction<TwoRegisterInstruction>(playbackSpeedIndex).registerA
val returnIndex = indexOfFirstInstructionOrThrow(playbackSpeedIndex, Opcode.RETURN_VOID) val returnIndex = indexOfFirstInstructionOrThrow(playbackSpeedIndex, Opcode.RETURN_VOID)
val insertIndex = playbackSpeedIndex + 1
val freeRegister = findFreeRegister(insertIndex, playbackSpeedRegister)
addInstructionsWithLabels( addInstructionsWithLabels(
playbackSpeedIndex + 1, insertIndex,
""" """
invoke-static { v$playbackSpeedRegister }, $EXTENSION_CLASS_DESCRIPTOR->playbackSpeedChanged(F)Z invoke-static { v$playbackSpeedRegister }, $EXTENSION_CLASS_DESCRIPTOR->playbackSpeedChanged(F)Z
move-result v$freeRegister move-result v$freeRegister

View File

@@ -39,9 +39,8 @@ val gmsCoreSupportPatch = gmsCoreSupportPatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )
} }

View File

@@ -13,9 +13,11 @@ import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
val bypassURLRedirectsPatch = bytecodePatch( val bypassURLRedirectsPatch = bytecodePatch(
name = "Bypass URL redirects", name = "Bypass URL redirects",
@@ -37,6 +39,7 @@ val bypassURLRedirectsPatch = bytecodePatch(
"19.45.38", "19.45.38",
"19.46.42", "19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )
@@ -80,3 +83,8 @@ internal fun Method.findUriParseIndex() = indexOfFirstInstruction {
val reference = getReference<MethodReference>() val reference = getReference<MethodReference>()
reference?.returnType == "Landroid/net/Uri;" && reference.name == "parse" reference?.returnType == "Landroid/net/Uri;" && reference.name == "parse"
} }
internal fun Method.findWebViewCheckCastIndex() = indexOfFirstInstruction {
val reference = getReference<TypeReference>()
opcode == Opcode.CHECK_CAST && reference?.type?.endsWith("/WebviewEndpointOuterClass${'$'}WebviewEndpoint;") == true
}

View File

@@ -11,12 +11,21 @@ internal val abUriParserFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("Ljava/lang/Object") returns("Ljava/lang/Object")
parameters("Ljava/lang/Object") parameters("Ljava/lang/Object")
strings(
"Found entityKey=`",
"` that does not contain a PlaylistVideoEntityId message as it's identifier.",
)
custom { method, _ -> custom { method, _ ->
method.findUriParseIndex() >= 0 method.findUriParseIndex() >= 0 && method.findWebViewCheckCastIndex() >= 0
}
}
/**
* Target 19.33+
*/
internal val httpUriParserFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
returns("Landroid/net/Uri")
parameters("Ljava/lang/String")
strings("https", "://", "https:")
custom { methodDef, _ ->
methodDef.findUriParseIndex() >= 0
} }
} }
@@ -47,19 +56,6 @@ internal val abUriParserLegacyFingerprint = fingerprint {
} }
} }
/**
* Target 19.33+
*/
internal val httpUriParserFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
returns("Landroid/net/Uri")
parameters("Ljava/lang/String")
strings("https", "https:", "://")
custom { methodDef, _ ->
methodDef.findUriParseIndex() >= 0
}
}
internal val httpUriParserLegacyFingerprint = fingerprint { internal val httpUriParserLegacyFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
returns("Landroid/net/Uri") returns("Landroid/net/Uri")

View File

@@ -45,9 +45,8 @@ val openLinksExternallyPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -10,7 +10,11 @@ import com.android.tools.smali.dexlib2.Opcode
* In 19.18+ this resolves to a different method. * In 19.18+ this resolves to a different method.
*/ */
internal val componentContextParserFingerprint = fingerprint { internal val componentContextParserFingerprint = fingerprint {
strings("Component was not found %s because it was removed due to duplicate converter bindings.") strings(
"TreeNode result must be set.",
// String is a partial match and changed slightly in 20.03+
"it was removed due to duplicate converter bindings."
)
} }
internal val lithoFilterFingerprint = fingerprint { internal val lithoFilterFingerprint = fingerprint {

View File

@@ -8,19 +8,21 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.playservice.is_19_18_or_greater import app.revanced.patches.youtube.misc.playservice.is_19_18_or_greater
import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater
import app.revanced.patches.youtube.misc.playservice.is_20_05_or_greater
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.util.findFreeRegister
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.* import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@@ -190,17 +192,7 @@ val lithoFilterPatch = bytecodePatch(
}, },
).registerA ).registerA
// Find a free temporary register. val freeRegister = findFreeRegister(insertHookIndex, identifierRegister, stringBuilderRegister)
val freeRegister = getInstruction<OneRegisterInstruction>(
// Immediately before is a StringBuilder append constant character.
indexOfFirstInstructionReversedOrThrow(insertHookIndex, Opcode.CONST_16),
).registerA
// Verify the temp register will not clobber the method result register.
if (stringBuilderRegister == freeRegister) {
throw PatchException("Free register will clobber StringBuilder register")
}
val invokeFilterInstructions = """ val invokeFilterInstructions = """
invoke-static { v$identifierRegister, v$stringBuilderRegister }, $EXTENSION_CLASS_DESCRIPTOR->filter(Ljava/lang/String;Ljava/lang/StringBuilder;)Z invoke-static { v$identifierRegister, v$stringBuilderRegister }, $EXTENSION_CLASS_DESCRIPTOR->filter(Ljava/lang/String;Ljava/lang/StringBuilder;)Z
move-result v$freeRegister move-result v$freeRegister
@@ -235,7 +227,10 @@ val lithoFilterPatch = bytecodePatch(
// 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
// all litho components have a null name and identifier/path filtering is completely broken. // all litho components have a null name and identifier/path filtering is completely broken.
if (is_19_25_or_greater) { //
// Flag was removed in 20.05. It appears a new flag might be used instead (45660109L),
// but if the flag is forced on then litho filtering still works correctly.
if (is_19_25_or_greater && !is_20_05_or_greater) {
lithoComponentNameUpbFeatureFlagFingerprint.method.apply { lithoComponentNameUpbFeatureFlagFingerprint.method.apply {
// Don't use return early, so the debug patch logs if this was originally on. // Don't use return early, so the debug patch logs if this was originally on.
val insertIndex = indexOfFirstInstructionOrThrow(Opcode.RETURN) val insertIndex = indexOfFirstInstructionOrThrow(Opcode.RETURN)

View File

@@ -46,6 +46,18 @@ var is_19_47_or_greater = false
private set private set
var is_19_49_or_greater = false var is_19_49_or_greater = false
private set private set
var is_20_02_or_greater = false
private set
var is_20_03_or_greater = false
private set
var is_20_05_or_greater = false
private set
var is_20_07_or_greater = false
private set
var is_20_09_or_greater = false
private set
var is_20_10_or_greater = false
private set
val versionCheckPatch = resourcePatch( val versionCheckPatch = resourcePatch(
description = "Uses the Play Store service version to find the major/minor version of the YouTube target app.", description = "Uses the Play Store service version to find the major/minor version of the YouTube target app.",
@@ -80,5 +92,11 @@ val versionCheckPatch = resourcePatch(
is_19_46_or_greater = 244705000 <= playStoreServicesVersion is_19_46_or_greater = 244705000 <= playStoreServicesVersion
is_19_47_or_greater = 244799000 <= playStoreServicesVersion is_19_47_or_greater = 244799000 <= playStoreServicesVersion
is_19_49_or_greater = 245005000 <= playStoreServicesVersion is_19_49_or_greater = 245005000 <= playStoreServicesVersion
is_20_02_or_greater = 250299000 <= playStoreServicesVersion
is_20_03_or_greater = 250405000 <= playStoreServicesVersion
is_20_05_or_greater = 250605000 <= playStoreServicesVersion
is_20_07_or_greater = 250805000 <= playStoreServicesVersion
is_20_09_or_greater = 251006000 <= playStoreServicesVersion
is_20_10_or_greater = 251105000 <= playStoreServicesVersion
} }
} }

View File

@@ -34,9 +34,8 @@ val removeTrackingQueryParameterPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -73,7 +73,22 @@ private val settingsResourcePatch = resourcePatch {
appearanceStringId = resourceMappings["string", "app_theme_appearance_dark"] appearanceStringId = resourceMappings["string", "app_theme_appearance_dark"]
arrayOf( arrayOf(
ResourceGroup("drawable", "revanced_settings_icon.xml"), ResourceGroup("drawable",
"revanced_settings_icon.xml",
"revanced_settings_screen_00_about.xml",
"revanced_settings_screen_01_ads.xml",
"revanced_settings_screen_02_alt_thumbnails.xml",
"revanced_settings_screen_03_feed.xml",
"revanced_settings_screen_04_general.xml",
"revanced_settings_screen_05_player.xml",
"revanced_settings_screen_06_shorts.xml",
"revanced_settings_screen_07_seekbar.xml",
"revanced_settings_screen_08_swipe_controls.xml",
"revanced_settings_screen_09_ryd.xml",
"revanced_settings_screen_10_sb.xml",
"revanced_settings_screen_11_misc.xml",
"revanced_settings_screen_12_video.xml",
),
ResourceGroup("layout", "revanced_settings_with_toolbar.xml"), ResourceGroup("layout", "revanced_settings_with_toolbar.xml"),
).forEach { resourceGroup -> ).forEach { resourceGroup ->
copyResources("settings", resourceGroup) copyResources("settings", resourceGroup)
@@ -159,6 +174,8 @@ val settingsPatch = bytecodePatch(
// Add an "about" preference to the top. // Add an "about" preference to the top.
preferences += NonInteractivePreference( preferences += NonInteractivePreference(
key = "revanced_settings_screen_00_about", key = "revanced_settings_screen_00_about",
icon = "@drawable/revanced_settings_screen_00_about",
layout = "@layout/preference_with_icon",
summaryKey = null, summaryKey = null,
tag = "app.revanced.extension.youtube.settings.preference.ReVancedYouTubeAboutPreference", tag = "app.revanced.extension.youtube.settings.preference.ReVancedYouTubeAboutPreference",
selectable = true, selectable = true,
@@ -170,6 +187,10 @@ val settingsPatch = bytecodePatch(
) )
} }
PreferenceScreen.GENERAL_LAYOUT.addPreferences(
SwitchPreference("revanced_show_menu_icons")
)
PreferenceScreen.MISC.addPreferences( PreferenceScreen.MISC.addPreferences(
TextPreference( TextPreference(
key = null, key = null,
@@ -277,37 +298,53 @@ object PreferenceScreen : BasePreferenceScreen() {
val ADS = Screen( val ADS = Screen(
key = "revanced_settings_screen_01_ads", key = "revanced_settings_screen_01_ads",
summaryKey = null, summaryKey = null,
icon = "@drawable/revanced_settings_screen_01_ads",
layout = "@layout/preference_with_icon",
) )
val ALTERNATIVE_THUMBNAILS = Screen( val ALTERNATIVE_THUMBNAILS = Screen(
key = "revanced_settings_screen_02_alt_thumbnails", key = "revanced_settings_screen_02_alt_thumbnails",
summaryKey = null, summaryKey = null,
icon = "@drawable/revanced_settings_screen_02_alt_thumbnails",
layout = "@layout/preference_with_icon",
sorting = Sorting.UNSORTED, sorting = Sorting.UNSORTED,
) )
val FEED = Screen( val FEED = Screen(
key = "revanced_settings_screen_03_feed", key = "revanced_settings_screen_03_feed",
summaryKey = null, summaryKey = null,
icon = "@drawable/revanced_settings_screen_03_feed",
layout = "@layout/preference_with_icon",
) )
val GENERAL_LAYOUT = Screen( val GENERAL_LAYOUT = Screen(
key = "revanced_settings_screen_04_general", key = "revanced_settings_screen_04_general",
summaryKey = null, summaryKey = null,
icon = "@drawable/revanced_settings_screen_04_general",
layout = "@layout/preference_with_icon",
) )
val PLAYER = Screen( val PLAYER = Screen(
key = "revanced_settings_screen_05_player", key = "revanced_settings_screen_05_player",
summaryKey = null, summaryKey = null,
icon = "@drawable/revanced_settings_screen_05_player",
layout = "@layout/preference_with_icon",
) )
val SHORTS = Screen( val SHORTS = Screen(
key = "revanced_settings_screen_06_shorts", key = "revanced_settings_screen_06_shorts",
summaryKey = null, summaryKey = null,
icon = "@drawable/revanced_settings_screen_06_shorts",
layout = "@layout/preference_with_icon",
) )
val SEEKBAR = Screen( val SEEKBAR = Screen(
key = "revanced_settings_screen_07_seekbar", key = "revanced_settings_screen_07_seekbar",
summaryKey = null, summaryKey = null,
) icon = "@drawable/revanced_settings_screen_07_seekbar",
layout = "@layout/preference_with_icon",
)
val SWIPE_CONTROLS = Screen( val SWIPE_CONTROLS = Screen(
key = "revanced_settings_screen_08_swipe_controls", key = "revanced_settings_screen_08_swipe_controls",
summaryKey = null, summaryKey = null,
icon = "@drawable/revanced_settings_screen_08_swipe_controls",
layout = "@layout/preference_with_icon",
sorting = Sorting.UNSORTED, sorting = Sorting.UNSORTED,
) )
@@ -317,10 +354,14 @@ object PreferenceScreen : BasePreferenceScreen() {
val MISC = Screen( val MISC = Screen(
key = "revanced_settings_screen_11_misc", key = "revanced_settings_screen_11_misc",
summaryKey = null, summaryKey = null,
icon = "@drawable/revanced_settings_screen_11_misc",
layout = "@layout/preference_with_icon",
) )
val VIDEO = Screen( val VIDEO = Screen(
key = "revanced_settings_screen_12_video", key = "revanced_settings_screen_12_video",
summaryKey = null, summaryKey = null,
icon = "@drawable/revanced_settings_screen_12_video",
layout = "@layout/preference_with_icon",
sorting = Sorting.BY_KEY, sorting = Sorting.BY_KEY,
) )

View File

@@ -7,6 +7,8 @@ import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPref
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.shared.misc.spoof.spoofVideoStreamsPatch import app.revanced.patches.shared.misc.spoof.spoofVideoStreamsPatch
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
import app.revanced.patches.youtube.misc.playservice.is_20_03_or_greater
import app.revanced.patches.youtube.misc.playservice.is_20_10_or_greater
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.settings.settingsPatch
@@ -18,9 +20,8 @@ val spoofVideoStreamsPatch = spoofVideoStreamsPatch({
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )
@@ -31,6 +32,10 @@ val spoofVideoStreamsPatch = spoofVideoStreamsPatch({
) )
}, { }, {
is_19_34_or_greater is_19_34_or_greater
}, {
is_20_10_or_greater
}, {
is_20_03_or_greater
}, { }, {
addResources("youtube", "misc.fix.playback.spoofVideoStreamsPatch") addResources("youtube", "misc.fix.playback.spoofVideoStreamsPatch")

View File

@@ -25,9 +25,8 @@ val zoomHapticsPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -45,9 +45,8 @@ val forceOriginalAudioPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -32,9 +32,8 @@ val disableHdrPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
), ),
) )

View File

@@ -2,11 +2,65 @@ package app.revanced.patches.youtube.video.playerresponse
import app.revanced.patcher.fingerprint import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import org.stringtemplate.v4.compiler.Bytecode.instructions
/** /**
* For targets 19.25 and later. * For targets 20.10 and later.
*/ */
internal val playerParameterBuilderFingerprint = fingerprint { internal val playerParameterBuilderFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("L")
parameters(
"Ljava/lang/String;", // VideoId.
"[B",
"Ljava/lang/String;", // Player parameters proto buffer.
"Ljava/lang/String;",
"I",
"Z",
"I",
"L",
"Ljava/util/Set;",
"Ljava/lang/String;",
"Ljava/lang/String;",
"L",
"Z", // Appears to indicate if the video id is being opened or is currently playing.
"Z",
"Z",
"Z"
)
strings("psps")
}
/**
* For targets 20.02 to 20.09.
*/
internal val playerParameterBuilder2002Fingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("L")
parameters(
"Ljava/lang/String;", // VideoId.
"[B",
"Ljava/lang/String;", // Player parameters proto buffer.
"Ljava/lang/String;",
"I",
"I",
"L", // 19.25+ parameter
"Ljava/util/Set;",
"Ljava/lang/String;",
"Ljava/lang/String;",
"L",
"Z", // Appears to indicate if the video id is being opened or is currently playing.
"Z",
"Z",
"Z",
)
strings("psps")
}
/**
* For targets 19.25 to 19.50.
*/
internal val playerParameterBuilder1925Fingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("L") returns("L")
parameters( parameters(

View File

@@ -1,11 +1,14 @@
package app.revanced.patches.youtube.video.playerresponse package app.revanced.patches.youtube.video.playerresponse
import app.revanced.patcher.Fingerprint
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.playservice.is_19_23_or_greater import app.revanced.patches.youtube.misc.playservice.is_19_23_or_greater
import app.revanced.patches.youtube.misc.playservice.is_20_02_or_greater
import app.revanced.patches.youtube.misc.playservice.is_20_10_or_greater
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
private val hooks = mutableSetOf<Hook>() private val hooks = mutableSetOf<Hook>()
@@ -35,15 +38,21 @@ val playerResponseMethodHookPatch = bytecodePatch {
) )
execute { execute {
playerResponseMethod = if (is_19_23_or_greater) { val fingerprint : Fingerprint
if (is_20_10_or_greater) {
parameterIsShortAndOpeningOrPlaying = 13
fingerprint = playerParameterBuilderFingerprint
} else if (is_20_02_or_greater) {
parameterIsShortAndOpeningOrPlaying = 12 parameterIsShortAndOpeningOrPlaying = 12
fingerprint = playerParameterBuilder2002Fingerprint
playerParameterBuilderFingerprint } else if (is_19_23_or_greater) {
parameterIsShortAndOpeningOrPlaying = 12
fingerprint = playerParameterBuilder1925Fingerprint
} else { } else {
parameterIsShortAndOpeningOrPlaying = 11 parameterIsShortAndOpeningOrPlaying = 11
fingerprint = playerParameterBuilderLegacyFingerprint
playerParameterBuilderLegacyFingerprint }
}.method playerResponseMethod = fingerprint.method
// On some app targets the method has too many registers pushing the parameters past v15. // On some app targets the method has too many registers pushing the parameters past v15.
// If needed, move the parameters to 4-bit registers, so they can be passed to the extension. // If needed, move the parameters to 4-bit registers, so they can be passed to the extension.

View File

@@ -27,9 +27,8 @@ val videoQualityPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
) )
) )

View File

@@ -32,9 +32,8 @@ val playbackSpeedPatch = bytecodePatch(
"19.25.37", "19.25.37",
"19.34.42", "19.34.42",
"19.43.41", "19.43.41",
"19.45.38",
"19.46.42",
"19.47.53", "19.47.53",
"20.07.39",
) )
) )

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