diff --git a/.gitignore b/.gitignore index a88ac46b2..9f2e41679 100644 --- a/.gitignore +++ b/.gitignore @@ -124,6 +124,8 @@ node_modules/ # gradle properties, due to Github token ./gradle.properties + .DS_Store local.properties __pycache__ +venv diff --git a/CHANGELOG.md b/CHANGELOG.md index 728e764ab..78a13c2cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,31 @@ +# [2.230.0-dev.1](https://github.com/anddea/revanced-patches/compare/v2.229.0...v2.230.0-dev.1) (2024-09-30) + + +### Bug Fixes + +* **YouTube - Hide feed components:** `Hide carousel shelf` setting sometimes hides the library shelf ([8c3a5d2](https://github.com/anddea/revanced-patches/commit/8c3a5d2fd08cdca5cf66324cc2a44b722e7062cc)) +* **YouTube - Player components:** The `Disable player popup panels` setting disables the engagement panel in Mix playlists on certain YouTube versions ([63c463c](https://github.com/anddea/revanced-patches/commit/63c463ca2bebd43c85e79609275f72bf4176f242)) +* **YouTube - Settings:** `Search bar in settings` can't find `RYD` and `SponsorBlock` settings ([ab222a6](https://github.com/anddea/revanced-patches/commit/ab222a672317ec7d00d566b1ca655b7b5c9a78cd)) +* **YouTube Music - Disable Cairo splash animation:** Some versions are recognized as unpatchable even though they can be patched ([1e74ff9](https://github.com/anddea/revanced-patches/commit/1e74ff94811097370e4c0f0d05dc429601e8f05c)) +* **YouTube Music - Player components:** `Remember shuffle state` setting does not remember the correct state ([18482b2](https://github.com/anddea/revanced-patches/commit/18482b2e6b57d2eea95527a05e9d86674446c052)) +* **YouTube Music - SponsorBlock:** SponsorBlock does not skip segments at the beginning of a video when in the background ([e895e6f](https://github.com/anddea/revanced-patches/commit/e895e6f5c638df5e2233cc50dc82de9ccfe89df0)) + + +### Features + +* **Custom branding icon:** Add `MMT Orange`, `MMT Pink`, `MMT Turquoise` ([e203ad1](https://github.com/anddea/revanced-patches/commit/e203ad159e8717a2042a978e1c6cee04fa8ce745)) +* **YouTube - Change start page:** Add `Change start page type` setting ([251d5d7](https://github.com/anddea/revanced-patches/commit/251d5d726061aff08ebe190513e10862db7c4856)) +* **YouTube - Custom Shorts action buttons:** Add `Cairo` ([f3b6717](https://github.com/anddea/revanced-patches/commit/f3b67174da909ab07d4b04bef14d5d7ae672cc3b)) +* **YouTube - Hide feed components:** Add `Hide related videos` setting ([a82c9ba](https://github.com/anddea/revanced-patches/commit/a82c9bac56e875417e8d0632d5e4cb14a3e4c4aa)) +* **YouTube - Hide feed components:** Add `Hide UPCOMING video` setting ([ec9d641](https://github.com/anddea/revanced-patches/commit/ec9d6419df2ed3bd13c4171a92216314202802a1)) +* **YouTube - Navigation bar components:** Add `Hide navigation bar` setting ([5936015](https://github.com/anddea/revanced-patches/commit/593601526bd10a6976d108d1d8689c44cf6331e9)) +* **YouTube - Shorts Component:** Add `Disable Like button animation` setting ([f9709d3](https://github.com/anddea/revanced-patches/commit/f9709d3b5661abfe73b0ebc1273e8b521aa695be)) +* **YouTube - Shorts components:** Add `Height percentage of empty space` setting ([b214aa5](https://github.com/anddea/revanced-patches/commit/b214aa5a8eed5a5929806f1ddbbd71bfc30effe6)) +* **YouTube - Shorts components:** Add `Hide stickers` setting ([49cf0fd](https://github.com/anddea/revanced-patches/commit/49cf0fd5c1bf1289944b0e5e78444ae9c23ced60)) +* **YouTube Music - Settings:** Add `Open default app settings` setting ([71b11cf](https://github.com/anddea/revanced-patches/commit/71b11cf0c43439b130cb22331252c5940d9229cb)) +* **YouTube:** Add `Hide shortcuts` patch ([2435c4f](https://github.com/anddea/revanced-patches/commit/2435c4f781596d0b370e8ca244a30dbdc793c696)) +* **YouTube:** Add `Hook YouTube Music actions` patch ([72b61d1](https://github.com/anddea/revanced-patches/commit/72b61d1bc2bac38e38e9ae70a1e7b8a6d0fc03ee)) + # [2.229.0](https://github.com/anddea/revanced-patches/compare/v2.228.0...v2.229.0) (2024-09-30) diff --git a/README.md b/README.md index ab8639efd..ac8d64321 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,8 @@ Check the [wiki](https://github.com/anddea/revanced-patches/wiki) for resources | `Hide layout components` | Adds options to hide general layout components. | 18.29.38 ~ 19.16.39 | | `Hide player buttons` | Adds options to hide buttons in the video player. | 18.29.38 ~ 19.16.39 | | `Hide player flyout menu` | Adds options to hide player flyout menu components. | 18.29.38 ~ 19.16.39 | +| `Hide shortcuts` | Remove, at compile time, the app shortcuts that appears when app icon is long pressed. | 18.29.38 ~ 19.16.39 | +| `Hook YouTube Music actions` | Adds support for opening music in RVX Music using the in-app YouTube Music button. | 18.29.38 ~ 19.16.39 | | `Hook download actions` | Adds support to download videos with an external downloader app using the in-app download button. | 18.29.38 ~ 19.16.39 | | `Layout switch` | Adds an option to spoof the dpi in order to use a tablet or phone layout. | 18.29.38 ~ 19.16.39 | | `MaterialYou` | Applies the MaterialYou theme for Android 12+ devices. | 18.29.38 ~ 19.16.39 | @@ -79,42 +81,42 @@ Check the [wiki](https://github.com/anddea/revanced-patches/wiki) for resources | 💊 Patch | 📜 Description | 🏹 Target Version | |:--------:|:--------------:|:-----------------:| -| `Amoled` | Applies a pure black theme to some components. | 6.20.51 ~ 7.16.52 | -| `Bitrate default value` | Sets the audio quality to 'Always High' when you first install the app. | 6.20.51 ~ 7.16.52 | -| `Bypass image region restrictions` | Adds an option to use a different host for static images, so that images blocked in some countries can be received. | 6.20.51 ~ 7.16.52 | -| `Certificate spoof` | Enables YouTube Music to work with Android Auto by spoofing the YouTube Music certificate. | 6.20.51 ~ 7.16.52 | -| `Change share sheet` | Add option to change from in-app share sheet to system share sheet. | 6.20.51 ~ 7.16.52 | -| `Change start page` | Adds an option to set which page the app opens in instead of the homepage. | 6.20.51 ~ 7.16.52 | -| `Custom branding icon for YouTube Music` | Changes the YouTube Music app icon to the icon specified in options.json. | 6.20.51 ~ 7.16.52 | -| `Custom branding name for YouTube Music` | Renames the YouTube Music app to the name specified in options.json. | 6.20.51 ~ 7.16.52 | -| `Custom header for YouTube Music` | Applies a custom header in the top left corner within the app. | 6.20.51 ~ 7.16.52 | -| `Disable Cairo splash animation` | Adds an option to disable Cairo splash animation. | 7.06.54 ~ 7.16.52 | -| `Disable auto captions` | Adds an option to disable captions from being automatically enabled. | 6.20.51 ~ 7.16.52 | -| `Disable dislike redirection` | Adds an option to disable redirection to the next track when clicking the Dislike button. | 6.20.51 ~ 7.16.52 | -| `Enable OPUS codec` | Adds an option to use the OPUS audio codec instead of the MP4A audio codec. | 6.20.51 ~ 7.16.52 | -| `Enable debug logging` | Adds an option to enable debug logging. | 6.20.51 ~ 7.16.52 | -| `Enable landscape mode` | Adds an option to enable landscape mode when rotating the screen on phones. | 6.20.51 ~ 7.16.52 | -| `Flyout menu components` | Adds options to hide or change flyout menu components. | 6.20.51 ~ 7.16.52 | -| `GmsCore support` | Allows patched Google apps to run without root and under a different package name by using GmsCore instead of Google Play Services. | 6.20.51 ~ 7.16.52 | -| `Hide account components` | Adds options to hide components related to the account menu. | 6.20.51 ~ 7.16.52 | -| `Hide action bar components` | Adds options to hide action bar components and replace the offline download button with an external download button. | 6.20.51 ~ 7.16.52 | -| `Hide ads` | Adds options to hide ads. | 6.20.51 ~ 7.16.52 | -| `Hide layout components` | Adds options to hide general layout components. | 6.20.51 ~ 7.16.52 | -| `Hide overlay filter` | Removes, at compile time, the dark overlay that appears when player flyout menus are open. | 6.20.51 ~ 7.16.52 | -| `Hide player overlay filter` | Removes, at compile time, the dark overlay that appears when single-tapping in the player. | 6.20.51 ~ 7.16.52 | -| `Navigation bar components` | Adds options to hide or change components related to the navigation bar. | 6.20.51 ~ 7.16.52 | -| `Player components` | Adds options to hide or change components related to the player. | 6.20.51 ~ 7.16.52 | -| `Remove background playback restrictions` | Removes restrictions on background playback, including for kids videos. | 6.20.51 ~ 7.16.52 | -| `Remove viewer discretion dialog` | Adds an option to remove the dialog that appears when opening a video that has been age-restricted by accepting it automatically. This does not bypass the age restriction. | 6.20.51 ~ 7.16.52 | -| `Restore old style library shelf` | Adds an option to return the Library tab to the old style. | 6.20.51 ~ 7.16.52 | -| `Return YouTube Dislike` | Adds an option to show the dislike count of songs using the Return YouTube Dislike API. | 6.20.51 ~ 7.16.52 | -| `Sanitize sharing links` | Adds an option to remove tracking query parameters from URLs when sharing links. | 6.20.51 ~ 7.16.52 | -| `Settings for YouTube Music` | Applies mandatory patches to implement ReVanced Extended settings into the application. | 6.20.51 ~ 7.16.52 | -| `SponsorBlock` | Adds options to enable and configure SponsorBlock, which can skip undesired video segments, such as non-music sections. | 6.20.51 ~ 7.16.52 | -| `Spoof app version` | Adds options to spoof the YouTube Music client version. This can remove the radio mode restriction in Canadian regions or disable real-time lyrics. | 6.20.51 ~ 7.16.52 | -| `Translations` | Adds Crowdin translations for YouTube Music. | 6.20.51 ~ 7.16.52 | -| `Video playback` | Adds options to customize settings related to video playback, such as default video quality and playback speed. | 6.20.51 ~ 7.16.52 | -| `Visual preferences icons` | Adds icons to specific preferences in the settings. | 6.20.51 ~ 7.16.52 | +| `Amoled` | Applies a pure black theme to some components. | 6.20.51 ~ 7.16.53 | +| `Bitrate default value` | Sets the audio quality to 'Always High' when you first install the app. | 6.20.51 ~ 7.16.53 | +| `Bypass image region restrictions` | Adds an option to use a different host for static images, so that images blocked in some countries can be received. | 6.20.51 ~ 7.16.53 | +| `Certificate spoof` | Enables YouTube Music to work with Android Auto by spoofing the YouTube Music certificate. | 6.20.51 ~ 7.16.53 | +| `Change share sheet` | Add option to change from in-app share sheet to system share sheet. | 6.20.51 ~ 7.16.53 | +| `Change start page` | Adds an option to set which page the app opens in instead of the homepage. | 6.20.51 ~ 7.16.53 | +| `Custom branding icon for YouTube Music` | Changes the YouTube Music app icon to the icon specified in options.json. | 6.20.51 ~ 7.16.53 | +| `Custom branding name for YouTube Music` | Renames the YouTube Music app to the name specified in options.json. | 6.20.51 ~ 7.16.53 | +| `Custom header for YouTube Music` | Applies a custom header in the top left corner within the app. | 6.20.51 ~ 7.16.53 | +| `Disable Cairo splash animation` | Adds an option to disable Cairo splash animation. | 7.06.54 ~ 7.16.53 | +| `Disable auto captions` | Adds an option to disable captions from being automatically enabled. | 6.20.51 ~ 7.16.53 | +| `Disable dislike redirection` | Adds an option to disable redirection to the next track when clicking the Dislike button. | 6.20.51 ~ 7.16.53 | +| `Enable OPUS codec` | Adds an option to use the OPUS audio codec instead of the MP4A audio codec. | 6.20.51 ~ 7.16.53 | +| `Enable debug logging` | Adds an option to enable debug logging. | 6.20.51 ~ 7.16.53 | +| `Enable landscape mode` | Adds an option to enable landscape mode when rotating the screen on phones. | 6.20.51 ~ 7.16.53 | +| `Flyout menu components` | Adds options to hide or change flyout menu components. | 6.20.51 ~ 7.16.53 | +| `GmsCore support` | Allows patched Google apps to run without root and under a different package name by using GmsCore instead of Google Play Services. | 6.20.51 ~ 7.16.53 | +| `Hide account components` | Adds options to hide components related to the account menu. | 6.20.51 ~ 7.16.53 | +| `Hide action bar components` | Adds options to hide action bar components and replace the offline download button with an external download button. | 6.20.51 ~ 7.16.53 | +| `Hide ads` | Adds options to hide ads. | 6.20.51 ~ 7.16.53 | +| `Hide layout components` | Adds options to hide general layout components. | 6.20.51 ~ 7.16.53 | +| `Hide overlay filter` | Removes, at compile time, the dark overlay that appears when player flyout menus are open. | 6.20.51 ~ 7.16.53 | +| `Hide player overlay filter` | Removes, at compile time, the dark overlay that appears when single-tapping in the player. | 6.20.51 ~ 7.16.53 | +| `Navigation bar components` | Adds options to hide or change components related to the navigation bar. | 6.20.51 ~ 7.16.53 | +| `Player components` | Adds options to hide or change components related to the player. | 6.20.51 ~ 7.16.53 | +| `Remove background playback restrictions` | Removes restrictions on background playback, including for kids videos. | 6.20.51 ~ 7.16.53 | +| `Remove viewer discretion dialog` | Adds an option to remove the dialog that appears when opening a video that has been age-restricted by accepting it automatically. This does not bypass the age restriction. | 6.20.51 ~ 7.16.53 | +| `Restore old style library shelf` | Adds an option to return the Library tab to the old style. | 6.20.51 ~ 7.16.53 | +| `Return YouTube Dislike` | Adds an option to show the dislike count of songs using the Return YouTube Dislike API. | 6.20.51 ~ 7.16.53 | +| `Sanitize sharing links` | Adds an option to remove tracking query parameters from URLs when sharing links. | 6.20.51 ~ 7.16.53 | +| `Settings for YouTube Music` | Applies mandatory patches to implement ReVanced Extended settings into the application. | 6.20.51 ~ 7.16.53 | +| `SponsorBlock` | Adds options to enable and configure SponsorBlock, which can skip undesired video segments, such as non-music sections. | 6.20.51 ~ 7.16.53 | +| `Spoof app version` | Adds options to spoof the YouTube Music client version. This can remove the radio mode restriction in Canadian regions or disable real-time lyrics. | 6.20.51 ~ 7.16.53 | +| `Translations` | Adds Crowdin translations for YouTube Music. | 6.20.51 ~ 7.16.53 | +| `Video playback` | Adds options to customize settings related to video playback, such as default video quality and playback speed. | 6.20.51 ~ 7.16.53 | +| `Visual preferences icons` | Adds icons to specific preferences in the settings. | 6.20.51 ~ 7.16.53 | ### [📦 `com.reddit.frontpage`](https://play.google.com/store/apps/details?id=com.reddit.frontpage) @@ -175,11 +177,10 @@ Example: "name": "com.google.android.apps.youtube.music", "versions": [ "6.20.51", - "6.29.58", - "6.33.52", + "6.29.59", "6.42.55", "6.51.53", - "7.16.52" + "7.16.53" ] } ], diff --git a/api/revanced-patches.api b/api/revanced-patches.api index 34f40f9fb..b84d18ce6 100644 --- a/api/revanced-patches.api +++ b/api/revanced-patches.api @@ -68,8 +68,9 @@ public final class app/revanced/patches/music/general/components/LayoutComponent public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } -public final class app/revanced/patches/music/general/components/fingerprints/SearchBarFingerprint : app/revanced/util/fingerprint/MethodReferenceNameFingerprint { +public final class app/revanced/patches/music/general/components/fingerprints/SearchBarFingerprint : app/revanced/patcher/fingerprint/MethodFingerprint { public static final field INSTANCE Lapp/revanced/patches/music/general/components/fingerprints/SearchBarFingerprint; + public final fun indexOfVisibilityInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;)I } public final class app/revanced/patches/music/general/components/fingerprints/SearchBarParentFingerprint : app/revanced/patcher/fingerprint/MethodFingerprint { @@ -243,12 +244,6 @@ public final class app/revanced/patches/music/utils/compatibility/Constants { public final fun getCOMPATIBLE_PACKAGE ()Ljava/util/Set; } -public final class app/revanced/patches/music/utils/fix/accessibility/AccessibilityNodeInfoPatch : app/revanced/patcher/patch/BytecodePatch { - public static final field INSTANCE Lapp/revanced/patches/music/utils/fix/accessibility/AccessibilityNodeInfoPatch; - public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V - public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V -} - public final class app/revanced/patches/music/utils/fix/androidauto/AndroidAutoCertificatePatch : app/revanced/util/patch/BaseBytecodePatch { public static final field INSTANCE Lapp/revanced/patches/music/utils/fix/androidauto/AndroidAutoCertificatePatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V @@ -350,6 +345,7 @@ public final class app/revanced/patches/music/utils/resourceid/SharedResourceIdP public final fun getInterstitialsContainer ()J public final fun getIsTablet ()J public final fun getLikeDislikeContainer ()J + public final fun getMainActivityLaunchAnimation ()J public final fun getMenuEntry ()J public final fun getMiniPlayerDefaultText ()J public final fun getMiniPlayerMdxPlaying ()J @@ -392,6 +388,7 @@ public final class app/revanced/patches/music/utils/resourceid/SharedResourceIdP public final fun setInterstitialsContainer (J)V public final fun setIsTablet (J)V public final fun setLikeDislikeContainer (J)V + public final fun setMainActivityLaunchAnimation (J)V public final fun setMenuEntry (J)V public final fun setMiniPlayerDefaultText (J)V public final fun setMiniPlayerMdxPlaying (J)V @@ -517,11 +514,8 @@ public final class app/revanced/patches/music/utils/videotype/VideoTypeHookPatch public final class app/revanced/patches/music/video/information/VideoInformationPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/music/video/information/VideoInformationPatch; - public static field rectangleFieldName Ljava/lang/String; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V - public final fun getRectangleFieldName ()Ljava/lang/String; - public final fun setRectangleFieldName (Ljava/lang/String;)V } public final class app/revanced/patches/music/video/playback/CustomPlaybackSpeedPatch : app/revanced/patches/shared/customspeed/BaseCustomPlaybackSpeedPatch { @@ -534,13 +528,6 @@ public final class app/revanced/patches/music/video/playback/VideoPlaybackPatch public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } -public final class app/revanced/patches/music/video/videoid/VideoIdPatch : app/revanced/patcher/patch/BytecodePatch { - public static final field INSTANCE Lapp/revanced/patches/music/video/videoid/VideoIdPatch; - public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V - public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V - public final fun hookVideoId (Ljava/lang/String;)V -} - public final class app/revanced/patches/reddit/ad/banner/BannerAdsPatch : app/revanced/patcher/patch/ResourcePatch { public static final field INSTANCE Lapp/revanced/patches/reddit/ad/banner/BannerAdsPatch; public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V @@ -1003,6 +990,13 @@ public final class app/revanced/patches/youtube/general/miniplayer/MiniplayerPat public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } +public final class app/revanced/patches/youtube/general/music/YouTubeMusicActionsPatch : app/revanced/util/patch/BaseBytecodePatch, java/io/Closeable { + public static final field INSTANCE Lapp/revanced/patches/youtube/general/music/YouTubeMusicActionsPatch; + public fun close ()V + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + public final class app/revanced/patches/youtube/general/navigation/NavigationBarComponentsPatch : app/revanced/util/patch/BaseBytecodePatch { public static final field INSTANCE Lapp/revanced/patches/youtube/general/navigation/NavigationBarComponentsPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V @@ -1043,7 +1037,7 @@ public final class app/revanced/patches/youtube/general/toolbar/ToolBarComponent public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } -public final class app/revanced/patches/youtube/general/toolbar/fingerprints/SearchBarFingerprint : app/revanced/util/fingerprint/MethodReferenceNameFingerprint { +public final class app/revanced/patches/youtube/general/toolbar/fingerprints/SearchBarFingerprint : app/revanced/patcher/fingerprint/MethodFingerprint { public static final field INSTANCE Lapp/revanced/patches/youtube/general/toolbar/fingerprints/SearchBarFingerprint; } @@ -1092,6 +1086,12 @@ public final class app/revanced/patches/youtube/layout/playerbuttonbg/PlayerButt public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V } +public final class app/revanced/patches/youtube/layout/shortcut/ShortcutPatch : app/revanced/util/patch/BaseResourcePatch { + public static final field INSTANCE Lapp/revanced/patches/youtube/layout/shortcut/ShortcutPatch; + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V + public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V +} + public final class app/revanced/patches/youtube/layout/theme/BaseThemePatch : app/revanced/patcher/patch/ResourcePatch { public static final field INSTANCE Lapp/revanced/patches/youtube/layout/theme/BaseThemePatch; public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V @@ -1296,7 +1296,7 @@ public final class app/revanced/patches/youtube/shorts/components/ShortsComponen public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } -public final class app/revanced/patches/youtube/shorts/components/ShortsNavigationBarPatch : app/revanced/patcher/patch/BytecodePatch { +public final class app/revanced/patches/youtube/shorts/components/ShortsNavigationBarPatch : app/revanced/util/patch/MultiMethodBytecodePatch { public static final field INSTANCE Lapp/revanced/patches/youtube/shorts/components/ShortsNavigationBarPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V @@ -1332,6 +1332,12 @@ public final class app/revanced/patches/youtube/swipe/controls/SwipeControlsPatc public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } +public final class app/revanced/patches/youtube/utils/bottomsheet/BottomSheetHookPatch : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/youtube/utils/bottomsheet/BottomSheetHookPatch; + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + public final class app/revanced/patches/youtube/utils/castbutton/CastButtonPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/youtube/utils/castbutton/CastButtonPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V @@ -1463,19 +1469,12 @@ public final class app/revanced/patches/youtube/utils/mainactivity/MainActivityR public final class app/revanced/patches/youtube/utils/navigation/NavigationBarHookPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/youtube/utils/navigation/NavigationBarHookPatch; + public final fun addBottomBarContainerHook (Ljava/lang/String;)V public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V public final fun getHookNavigationButtonCreated ()Lkotlin/jvm/functions/Function1; } -public final class app/revanced/patches/youtube/utils/navigation/fingerprints/MobileTopBarButtonOnClickFingerprint : app/revanced/patcher/fingerprint/MethodFingerprint { - public static final field INSTANCE Lapp/revanced/patches/youtube/utils/navigation/fingerprints/MobileTopBarButtonOnClickFingerprint; -} - -public final class app/revanced/patches/youtube/utils/navigation/fingerprints/SettingsActivityOnBackPressedFingerprint : app/revanced/patcher/fingerprint/MethodFingerprint { - public static final field INSTANCE Lapp/revanced/patches/youtube/utils/navigation/fingerprints/SettingsActivityOnBackPressedFingerprint; -} - public final class app/revanced/patches/youtube/utils/pip/PiPStateHookPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/youtube/utils/pip/PiPStateHookPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V @@ -1524,6 +1523,7 @@ public final class app/revanced/patches/youtube/utils/resourceid/SharedResourceI public final fun getBadgeLabel ()J public final fun getBar ()J public final fun getBarContainerHeight ()J + public final fun getBottomBarContainer ()J public final fun getBottomSheetFooterText ()J public final fun getBottomSheetRecyclerView ()J public final fun getBottomUiContainerStub ()J @@ -1537,6 +1537,7 @@ public final class app/revanced/patches/youtube/utils/resourceid/SharedResourceI public final fun getControlsLayoutStub ()J public final fun getDarkBackground ()J public final fun getDarkSplashAnimation ()J + public final fun getDesignBottomSheet ()J public final fun getDonationCompanion ()J public final fun getDrawerContentView ()J public final fun getDrawerResults ()J @@ -1587,6 +1588,7 @@ public final class app/revanced/patches/youtube/utils/resourceid/SharedResourceI public final fun getReelRightLikeIcon ()J public final fun getReelTimeBarPlayedColor ()J public final fun getReelVodTimeStampsContainer ()J + public final fun getReelWatchPlayer ()J public final fun getRelatedChipCloudMargin ()J public final fun getRightComment ()J public final fun getScrimOverlay ()J @@ -1626,6 +1628,7 @@ public final class app/revanced/patches/youtube/utils/resourceid/SharedResourceI public final fun setBadgeLabel (J)V public final fun setBar (J)V public final fun setBarContainerHeight (J)V + public final fun setBottomBarContainer (J)V public final fun setBottomSheetFooterText (J)V public final fun setBottomSheetRecyclerView (J)V public final fun setBottomUiContainerStub (J)V @@ -1639,6 +1642,7 @@ public final class app/revanced/patches/youtube/utils/resourceid/SharedResourceI public final fun setControlsLayoutStub (J)V public final fun setDarkBackground (J)V public final fun setDarkSplashAnimation (J)V + public final fun setDesignBottomSheet (J)V public final fun setDonationCompanion (J)V public final fun setDrawerContentView (J)V public final fun setDrawerResults (J)V @@ -1689,6 +1693,7 @@ public final class app/revanced/patches/youtube/utils/resourceid/SharedResourceI public final fun setReelRightLikeIcon (J)V public final fun setReelTimeBarPlayedColor (J)V public final fun setReelVodTimeStampsContainer (J)V + public final fun setReelWatchPlayer (J)V public final fun setRelatedChipCloudMargin (J)V public final fun setRightComment (J)V public final fun setScrimOverlay (J)V @@ -1738,7 +1743,8 @@ public final class app/revanced/patches/youtube/utils/settings/ResourceUtils { public static final field INSTANCE Lapp/revanced/patches/youtube/utils/settings/ResourceUtils; public static final field TARGET_PREFERENCE_PATH Ljava/lang/String; public static final field YOUTUBE_SETTINGS_PATH Ljava/lang/String; - public final fun addEntryValues (Lapp/revanced/patcher/data/ResourceContext;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + public final fun addEntryValues (Lapp/revanced/patcher/data/ResourceContext;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V + public static synthetic fun addEntryValues$default (Lapp/revanced/patches/youtube/utils/settings/ResourceUtils;Lapp/revanced/patcher/data/ResourceContext;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)V public final fun addPreference (Lapp/revanced/patcher/data/ResourceContext;[Ljava/lang/String;)V public final fun addPreferenceFragment (Lapp/revanced/patcher/data/ResourceContext;Ljava/lang/String;Ljava/lang/String;)V public final fun getIconType ()Ljava/lang/String; @@ -1844,89 +1850,52 @@ public final class app/revanced/patches/youtube/video/videoid/VideoIdPatch : app public final class app/revanced/util/BytecodeUtilsKt { public static final field REGISTER_TEMPLATE_REPLACEMENT Ljava/lang/String; - public static final fun addFieldAndInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lapp/revanced/patcher/data/BytecodeContext;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V + public static final fun addStaticFieldToIntegration (Lapp/revanced/patcher/data/BytecodeContext;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V + public static synthetic fun addStaticFieldToIntegration$default (Lapp/revanced/patcher/data/BytecodeContext;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)V public static final fun alsoResolve (Lapp/revanced/patcher/fingerprint/MethodFingerprint;Lapp/revanced/patcher/data/BytecodeContext;Lapp/revanced/patcher/fingerprint/MethodFingerprint;)Lapp/revanced/patcher/fingerprint/MethodFingerprintResult; - public static final fun checkIndex (IILcom/android/tools/smali/dexlib2/Opcode;)I - public static final fun checkIndex (IILjava/lang/String;)I - public static final fun containsMethodReferenceNameInstructionIndex (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)Z - public static final fun containsReferenceInstructionIndex (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)Z - public static final fun containsWideLiteralInstructionIndex (Lcom/android/tools/smali/dexlib2/iface/Method;J)Z + public static final fun containsWideLiteralInstructionValue (Lcom/android/tools/smali/dexlib2/iface/Method;J)Z + public static final fun findMethodOrThrow (Lapp/revanced/patcher/data/BytecodeContext;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod; + public static synthetic fun findMethodOrThrow$default (Lapp/revanced/patcher/data/BytecodeContext;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod; + public static final fun findMethodsOrThrow (Lapp/revanced/patcher/data/BytecodeContext;Ljava/lang/String;)Ljava/util/Set; public static final fun findMutableMethodOf (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lcom/android/tools/smali/dexlib2/iface/Method;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod; public static final fun findOpcodeIndicesReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/Opcode;)Ljava/util/List; public static final fun findOpcodeIndicesReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun getException (Lapp/revanced/patcher/fingerprint/MethodFingerprint;)Lapp/revanced/patcher/patch/PatchException; - public static final fun getStartsWithStringInstructionIndex (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I - public static final fun getStringInstructionIndex (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I - public static final fun getTargetIndex (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILcom/android/tools/smali/dexlib2/Opcode;)I - public static final fun getTargetIndex (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Lcom/android/tools/smali/dexlib2/Opcode;)I - public static final fun getTargetIndexOrThrow (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILcom/android/tools/smali/dexlib2/Opcode;)I - public static final fun getTargetIndexOrThrow (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Lcom/android/tools/smali/dexlib2/Opcode;)I - public static final fun getTargetIndexReversed (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILcom/android/tools/smali/dexlib2/Opcode;)I - public static final fun getTargetIndexReversed (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Lcom/android/tools/smali/dexlib2/Opcode;)I - public static final fun getTargetIndexReversedOrThrow (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILcom/android/tools/smali/dexlib2/Opcode;)I - public static final fun getTargetIndexReversedOrThrow (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Lcom/android/tools/smali/dexlib2/Opcode;)I - public static final fun getTargetIndexWithFieldReferenceName (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)I - public static final fun getTargetIndexWithFieldReferenceName (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I - public static final fun getTargetIndexWithFieldReferenceNameOrThrow (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)I - public static final fun getTargetIndexWithFieldReferenceNameOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I - public static final fun getTargetIndexWithFieldReferenceNameReversed (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)I - public static final fun getTargetIndexWithFieldReferenceNameReversed (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/String;)I - public static final fun getTargetIndexWithFieldReferenceNameReversedOrThrow (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)I - public static final fun getTargetIndexWithFieldReferenceNameReversedOrThrow (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/String;)I - public static final fun getTargetIndexWithFieldReferenceType (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)I - public static final fun getTargetIndexWithFieldReferenceType (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I - public static final fun getTargetIndexWithFieldReferenceTypeOrThrow (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)I - public static final fun getTargetIndexWithFieldReferenceTypeOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I - public static final fun getTargetIndexWithFieldReferenceTypeReversed (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)I - public static final fun getTargetIndexWithFieldReferenceTypeReversed (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/String;)I - public static final fun getTargetIndexWithFieldReferenceTypeReversedOrThrow (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)I - public static final fun getTargetIndexWithFieldReferenceTypeReversedOrThrow (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/String;)I - public static final fun getTargetIndexWithMethodReferenceName (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)I - public static final fun getTargetIndexWithMethodReferenceName (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I - public static final fun getTargetIndexWithMethodReferenceNameOrThrow (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)I - public static final fun getTargetIndexWithMethodReferenceNameOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I - public static final fun getTargetIndexWithMethodReferenceNameReversed (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)I - public static final fun getTargetIndexWithMethodReferenceNameReversed (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/String;)I - public static final fun getTargetIndexWithMethodReferenceNameReversedOrThrow (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)I - public static final fun getTargetIndexWithMethodReferenceNameReversedOrThrow (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/String;)I - public static final fun getTargetIndexWithReference (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)I - public static final fun getTargetIndexWithReference (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/String;)I - public static final fun getTargetIndexWithReference (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I - public static final fun getTargetIndexWithReferenceOrThrow (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)I - public static final fun getTargetIndexWithReferenceOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I - public static final fun getTargetIndexWithReferenceReversed (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)I - public static final fun getTargetIndexWithReferenceReversed (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/String;)I - public static final fun getTargetIndexWithReferenceReversedOrThrow (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)I - public static final fun getTargetIndexWithReferenceReversedOrThrow (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/String;)I + public static final fun getException (Lapp/revanced/util/fingerprint/MultiMethodFingerprint;)Lapp/revanced/patcher/patch/PatchException; public static final fun getWalkerMethod (Lapp/revanced/patcher/fingerprint/MethodFingerprintResult;Lapp/revanced/patcher/data/BytecodeContext;I)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod; public static final fun getWalkerMethod (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Lapp/revanced/patcher/data/BytecodeContext;I)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod; - public static final fun getWideLiteralInstructionIndex (Lcom/android/tools/smali/dexlib2/iface/Method;J)I public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;ILcom/android/tools/smali/dexlib2/Opcode;)I public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;ILkotlin/jvm/functions/Function1;)I - public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)I public static synthetic fun indexOfFirstInstruction$default (Lcom/android/tools/smali/dexlib2/iface/Method;ILcom/android/tools/smali/dexlib2/Opcode;ILjava/lang/Object;)I public static synthetic fun indexOfFirstInstruction$default (Lcom/android/tools/smali/dexlib2/iface/Method;ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)I public static final fun indexOfFirstInstructionOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;ILcom/android/tools/smali/dexlib2/Opcode;)I public static final fun indexOfFirstInstructionOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;ILkotlin/jvm/functions/Function1;)I + public static final fun indexOfFirstInstructionOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/Opcode;)I public static synthetic fun indexOfFirstInstructionOrThrow$default (Lcom/android/tools/smali/dexlib2/iface/Method;ILcom/android/tools/smali/dexlib2/Opcode;ILjava/lang/Object;)I public static synthetic fun indexOfFirstInstructionOrThrow$default (Lcom/android/tools/smali/dexlib2/iface/Method;ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)I public static final fun indexOfFirstInstructionReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lcom/android/tools/smali/dexlib2/Opcode;)I public static final fun indexOfFirstInstructionReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;)I public static synthetic fun indexOfFirstInstructionReversed$default (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lcom/android/tools/smali/dexlib2/Opcode;ILjava/lang/Object;)I public static synthetic fun indexOfFirstInstructionReversed$default (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)I + public static final fun indexOfFirstInstructionReversedOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/Opcode;)I public static final fun indexOfFirstInstructionReversedOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lcom/android/tools/smali/dexlib2/Opcode;)I public static final fun indexOfFirstInstructionReversedOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;)I public static synthetic fun indexOfFirstInstructionReversedOrThrow$default (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lcom/android/tools/smali/dexlib2/Opcode;ILjava/lang/Object;)I public static synthetic fun indexOfFirstInstructionReversedOrThrow$default (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)I - public static final fun indexOfWideLiteralInstructionOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;J)I + public static final fun indexOfFirstStringInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I + public static final fun indexOfFirstStringInstructionOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I + public static final fun indexOfFirstWideLiteralInstructionValue (Lcom/android/tools/smali/dexlib2/iface/Method;J)I + public static final fun indexOfFirstWideLiteralInstructionValueOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;J)I public static final fun injectHideViewCall (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;IILjava/lang/String;Ljava/lang/String;)V - public static final fun literalInstructionBooleanHook (Lapp/revanced/patcher/fingerprint/MethodFingerprint;ILjava/lang/String;)V - public static final fun literalInstructionBooleanHook (Lapp/revanced/patcher/fingerprint/MethodFingerprint;JLjava/lang/String;)V - public static final fun literalInstructionHook (Lapp/revanced/patcher/data/BytecodeContext;JLjava/lang/String;)V - public static final fun literalInstructionViewHook (Lapp/revanced/patcher/data/BytecodeContext;JLjava/lang/String;)V - public static final fun literalInstructionViewHook (Lapp/revanced/patcher/fingerprint/MethodFingerprint;JLjava/lang/String;)V - public static final fun literalInstructionViewHook (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;JLjava/lang/String;)V + public static final fun injectLiteralInstructionBooleanCall (Lapp/revanced/patcher/fingerprint/MethodFingerprint;ILjava/lang/String;)V + public static final fun injectLiteralInstructionBooleanCall (Lapp/revanced/patcher/fingerprint/MethodFingerprint;JLjava/lang/String;)V + public static final fun injectLiteralInstructionViewCall (Lapp/revanced/patcher/data/BytecodeContext;JLjava/lang/String;)V + public static final fun injectLiteralInstructionViewCall (Lapp/revanced/patcher/fingerprint/MethodFingerprint;JLjava/lang/String;)V + public static final fun injectLiteralInstructionViewCall (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;JLjava/lang/String;)V + public static final fun isDeprecated (Lapp/revanced/patcher/fingerprint/MethodFingerprint;)Z + public static final fun replaceLiteralInstructionCall (Lapp/revanced/patcher/data/BytecodeContext;JLjava/lang/String;)V public static final fun resultOrThrow (Lapp/revanced/patcher/fingerprint/MethodFingerprint;)Lapp/revanced/patcher/fingerprint/MethodFingerprintResult; + public static final fun resultOrThrow (Lapp/revanced/util/fingerprint/MultiMethodFingerprint;)Ljava/util/List; public static final fun returnEarly (Ljava/util/List;Z)V public static synthetic fun returnEarly$default (Ljava/util/List;ZILjava/lang/Object;)V public static final fun transformFields (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lkotlin/jvm/functions/Function1;)V @@ -1967,14 +1936,25 @@ public abstract class app/revanced/util/fingerprint/LiteralValueFingerprint : ap public synthetic fun (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function0;ILkotlin/jvm/internal/DefaultConstructorMarker;)V } -public abstract class app/revanced/util/fingerprint/MethodReferenceNameFingerprint : app/revanced/patcher/fingerprint/MethodFingerprint { - public fun (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function0;)V - public synthetic fun (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function0;ILkotlin/jvm/internal/DefaultConstructorMarker;)V +public abstract class app/revanced/util/fingerprint/MultiMethodFingerprint { + public static final field Companion Lapp/revanced/util/fingerprint/MultiMethodFingerprint$Companion; + public fun ()V + public fun (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun getAccessFlags ()Ljava/lang/Integer; + public final fun getCustomFingerprint ()Lkotlin/jvm/functions/Function2; + public final fun getOpcodes ()Ljava/lang/Iterable; + public final fun getParameters ()Ljava/lang/Iterable; + public final fun getResult ()Ljava/util/List; + public final fun getReturnType ()Ljava/lang/String; + public final fun getStrings ()Ljava/lang/Iterable; + public final fun setResult (Ljava/util/List;)V } -public abstract class app/revanced/util/fingerprint/ReferenceFingerprint : app/revanced/patcher/fingerprint/MethodFingerprint { - public fun (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function0;)V - public synthetic fun (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function0;ILkotlin/jvm/internal/DefaultConstructorMarker;)V +public final class app/revanced/util/fingerprint/MultiMethodFingerprint$Companion { + public final fun resolve (Lapp/revanced/util/fingerprint/MultiMethodFingerprint;Lapp/revanced/patcher/data/BytecodeContext;Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Z + public final fun resolve (Lapp/revanced/util/fingerprint/MultiMethodFingerprint;Lapp/revanced/patcher/data/BytecodeContext;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Z + public final fun resolve (Ljava/lang/Iterable;Lapp/revanced/patcher/data/BytecodeContext;Ljava/lang/Iterable;)V } public abstract class app/revanced/util/patch/BaseBytecodePatch : app/revanced/patcher/patch/BytecodePatch { @@ -1989,3 +1969,13 @@ public abstract class app/revanced/util/patch/BaseResourcePatch : app/revanced/p public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZZILkotlin/jvm/internal/DefaultConstructorMarker;)V } +public abstract class app/revanced/util/patch/MultiMethodBytecodePatch : app/revanced/patcher/patch/BytecodePatch { + public fun ()V + public fun (Ljava/util/Set;Ljava/util/Set;)V + public synthetic fun (Ljava/util/Set;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V + public final fun getFingerprints ()Ljava/util/Set; + public final fun getMultiFingerprints ()Ljava/util/Set; +} + diff --git a/gradle.properties b/gradle.properties index 614329b0b..8dffaad08 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true kotlin.code.style = official -version = 2.229.0 +version = 2.230.0-dev.1 diff --git a/patches.json b/patches.json index 7bcdacd9e..1766e544d 100644 --- a/patches.json +++ b/patches.json @@ -1 +1 @@ -[{"name":"Alternative thumbnails","description":"Adds options to replace video thumbnails using the DeArrow API or image captures from the video.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Ambient mode control","description":"Adds options to disable Ambient mode and to bypass Ambient mode restrictions.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Amoled","description":"Applies a pure black theme to some components.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Bitrate default value","description":"Sets the audio quality to \u0027Always High\u0027 when you first install the app.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Bypass image region restrictions","description":"Adds an option to use a different host for static images, so that images blocked in some countries can be received.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Bypass image region restrictions","description":"Adds an option to use a different host for static images, so that images blocked in some countries can be received.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Certificate spoof","description":"Enables YouTube Music to work with Android Auto by spoofing the YouTube Music certificate.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Change package name","description":"Changes the package name for Reddit to the name specified in options.json.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":false,"requiresIntegrations":false,"options":[{"key":"PackageNameReddit","default":"com.reddit.frontpage","values":{"Clone":"com.reddit.frontpage.revanced","Default":"com.reddit.frontpage.rvx","Original":"com.reddit.frontpage"},"title":"Package name of Reddit","description":"The name of the package to rename the app to.","required":true}]},{"name":"Change player flyout menu toggles","description":"Adds an option to use text toggles instead of switch toggles within the additional settings menu.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Change share sheet","description":"Add option to change from in-app share sheet to system share sheet.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Change share sheet","description":"Add option to change from in-app share sheet to system share sheet.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Change start page","description":"Adds an option to set which page the app opens in instead of the homepage.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Change start page","description":"Adds an option to set which page the app opens in instead of the homepage.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Change version code","description":"Changes the version code of the app to the value specified in options.json. Except when mounting, this can prevent app stores from updating the app and allow the app to be installed over an existing installation that has a higher version code. By default, the highest version code is set.","compatiblePackages":null,"use":false,"requiresIntegrations":false,"options":[{"key":"ChangeVersionCode","default":false,"values":null,"title":"Change version code","description":"Changes the version code of the app.","required":true},{"key":"VersionCode","default":"2147483647","values":null,"title":"Version code","description":"The version code to use. (1 ~ 2147483647)","required":true}]},{"name":"Custom Shorts action buttons","description":"Changes, at compile time, the icon of the action buttons of the Shorts player.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"IconType","default":"round","values":{"Outline":"outline","OutlineCircle":"outlinecircle","Round":"round","YouTube":"youtube","YouTubeOutline":"youtubeoutline"},"title":"Shorts icon style ","description":"The style of the icons for the action buttons in the Shorts player.","required":true}]},{"name":"Custom branding icon for YouTube","description":"Changes the YouTube app icon to the icon specified in options.json.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":false,"requiresIntegrations":false,"options":[{"key":"AppIcon","default":"Xisr Yellow","values":{"AFN Blue":"afn_blue","AFN Red":"afn_red","MMT":"mmt","MMT Blue":"mmt_blue","MMT Green":"mmt_green","MMT Yellow":"mmt_yellow","Revancify Blue":"revancify_blue","Revancify Red":"revancify_red","Vanced Black":"vanced_black","Vanced Light":"vanced_light","Xisr Yellow":"xisr_yellow","YouTube":"youtube"},"title":"App icon","description":"The icon to apply to the app.\n\nIf a path to a folder is provided, the folder must contain the following folders:\n\n- mipmap-xxxhdpi\n- mipmap-xxhdpi\n- mipmap-xhdpi\n- mipmap-hdpi\n- mipmap-mdpi\n\nEach of these folders must contain the following files:\n\n- adaptiveproduct_youtube_background_color_108.png\n- adaptiveproduct_youtube_foreground_color_108.png\n- ic_launcher.png\n- ic_launcher_round.png","required":true},{"key":"ChangeHeader","default":true,"values":null,"title":"Change header","description":"Apply the custom branding icon to the header.","required":true},{"key":"CustomHeader","default":"","values":null,"title":"Custom header","description":"The header to apply to the app.\n\nIf a path to a folder is provided, the folder must contain one or more of the following folders, depending on the DPI of the device:\n\n- drawable-xxxhdpi\n- drawable-xxhdpi\n- drawable-xhdpi\n- drawable-hdpi\n- drawable-mdpi\n\nEach of the folders must contain all of the following files:\n\n- yt_premium_wordmark_header_dark.png\n- yt_premium_wordmark_header_light.png\n- yt_wordmark_header_dark.png\n- yt_wordmark_header_light.png\n\nThe image dimensions must be as follows:\n- drawable-xxxhdpi: 512px x 192px\n- drawable-xxhdpi: 387px x 144px\n- drawable-xhdpi: 258px x 96px\n- drawable-hdpi: 194px x 72px\n- drawable-mdpi: 129px x 48px","required":true},{"key":"ChangeSplashIcon","default":true,"values":null,"title":"Change splash icons","description":"Apply the custom branding icon to the splash screen.","required":true},{"key":"RestoreOldSplashAnimation","default":true,"values":null,"title":"Restore old splash animation","description":"Restore the old style splash animation.","required":true}]},{"name":"Custom branding icon for YouTube Music","description":"Changes the YouTube Music app icon to the icon specified in options.json.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":false,"requiresIntegrations":false,"options":[{"key":"AppIcon","default":"Xisr Yellow","values":{"AFN Blue":"afn_blue","AFN Red":"afn_red","MMT":"mmt","MMT Blue":"mmt_blue","MMT Green":"mmt_green","MMT Yellow":"mmt_yellow","Revancify Blue":"revancify_blue","Revancify Red":"revancify_red","Vanced Black":"vanced_black","Vanced Light":"vanced_light","Xisr Yellow":"xisr_yellow","YouTube Music":"youtube_music"},"title":"App icon","description":"The icon to apply to the app.\n\nIf a path to a folder is provided, the folder must contain the following folders:\n\n- mipmap-xxxhdpi\n- mipmap-xxhdpi\n- mipmap-xhdpi\n- mipmap-hdpi\n- mipmap-mdpi\n\nEach of these folders must contain the following files:\n\n- adaptiveproduct_youtube_music_background_color_108.png\n- adaptiveproduct_youtube_music_foreground_color_108.png\n- ic_launcher_release.png","required":true},{"key":"ChangeHeader","default":true,"values":null,"title":"Change header","description":"Apply the custom branding icon to the header.","required":true},{"key":"ChangeSplashIcon","default":true,"values":null,"title":"Change splash icons","description":"Apply the custom branding icon to the splash screen.","required":true},{"key":"RestoreOldSplashIcon","default":false,"values":null,"title":"Restore old splash icon","description":"Restore the old style splash icon.\n\nIf you enable both the old style splash icon and the Cairo splash animation,\n\nOld style splash icon will appear first and then the Cairo splash animation will start.","required":true}]},{"name":"Custom branding name for Reddit","description":"Renames the Reddit app to the name specified in options.json.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":false,"requiresIntegrations":false,"options":[{"key":"AppName","default":"Reddit","values":{"Default":"RVX Reddit","Original":"Reddit"},"title":"App name","description":"The name of the app.","required":true}]},{"name":"Custom branding name for YouTube","description":"Renames the YouTube app to the name specified in options.json.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":false,"requiresIntegrations":false,"options":[{"key":"AppName","default":"RVX","values":{"ReVanced Extended":"ReVanced Extended","RVX":"RVX","YouTube RVX":"YouTube RVX","YouTube":"YouTube"},"title":"App name","description":"The name of the app.","required":true}]},{"name":"Custom branding name for YouTube Music","description":"Renames the YouTube Music app to the name specified in options.json.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":false,"requiresIntegrations":false,"options":[{"key":"AppNameNotification","default":"RVX Music","values":{"ReVanced Extended Music":"ReVanced Extended Music","RVX Music":"RVX Music","YouTube Music":"YouTube Music","YT Music":"YT Music"},"title":"App name in notification panel","description":"The name of the app as it appears in the notification panel.","required":true},{"key":"AppNameLauncher","default":"RVX Music","values":{"ReVanced Extended Music":"ReVanced Extended Music","RVX Music":"RVX Music","YouTube Music":"YouTube Music","YT Music":"YT Music"},"title":"App name in launcher","description":"The name of the app as it appears in the launcher.","required":true}]},{"name":"Custom double tap length","description":"Adds Double-tap to seek values that are specified in options.json.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"DoubleTapLengthArrays","default":"3, 5, 10, 15, 20, 30, 60, 120, 180","values":null,"title":"Double-tap to seek values","description":"A list of custom Double-tap to seek lengths to be added, separated by commas.","required":true}]},{"name":"Custom header for YouTube Music","description":"Applies a custom header in the top left corner within the app.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":false,"requiresIntegrations":false,"options":[{"key":"CustomHeader","default":"custom_branding_icon","values":{"Custom branding icon":"custom_branding_icon"},"title":"Custom header","description":"The header to apply to the app.\n\nPatch option \u0027Custom branding icon\u0027 applies only when:\n\n1. Patch \u0027Custom branding icon for YouTube Music\u0027 is included.\n2. Patch option for \u0027Custom branding icon for YouTube Music\u0027 is selected from the preset.\n\nIf a path to a folder is provided, the folder must contain one or more of the following folders, depending on the DPI of the device:\n\n- drawable-xxxhdpi\n- drawable-xxhdpi\n- drawable-xhdpi\n- drawable-hdpi\n- drawable-mdpi\n\nEach of the folders must contain all of the following files:\n\n- action_bar_logo.png\n- logo_music.png\n- ytm_logo.png\n\nThe image \u0027action_bar_logo.png\u0027 dimensions must be as follows:\n\n- drawable-xxxhdpi: 320px x 96px\n- drawable-xxhdpi: 240px x 72px\n- drawable-xhdpi: 160px x 48px\n- drawable-hdpi: 121px x 36px\n- drawable-mdpi: 80px x 24px\n\nThe image \u0027logo_music.png\u0027 dimensions must be as follows:\n\n- drawable-xxxhdpi: 576px x 200px\n- drawable-xxhdpi: 432px x 150px\n- drawable-xhdpi: 288px x 100px\n- drawable-hdpi: 217px x 76px\n- drawable-mdpi: 144px x 50px\n\nThe image \u0027ytm_logo.png\u0027 dimensions must be as follows:\n\n- drawable-xxxhdpi: 412px x 144px\n- drawable-xxhdpi: 309px x 108px\n- drawable-xhdpi: 206px x 72px\n- drawable-hdpi: 155px x 54px\n- drawable-mdpi: 103px x 36px","required":true}]},{"name":"Description components","description":"Adds options to hide and disable description components.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable Cairo splash animation","description":"Adds an option to disable Cairo splash animation.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["7.06.54","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable QUIC protocol","description":"Adds an option to disable CronetEngine\u0027s QUIC protocol.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable auto audio tracks","description":"Adds an option to disable audio tracks from being automatically enabled.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable auto captions","description":"Adds an option to disable captions from being automatically enabled.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable auto captions","description":"Adds an option to disable captions from being automatically enabled.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable dislike redirection","description":"Adds an option to disable redirection to the next track when clicking the Dislike button.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable haptic feedback","description":"Adds options to disable haptic feedback when swiping in the video player.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable resuming Shorts on startup","description":"Adds an option to disable the Shorts player from resuming on app startup when Shorts were last being watched.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable screenshot popup","description":"Adds an option to disable the popup that appears when taking a screenshot.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable splash animation","description":"Adds an option to disable the splash animation on app startup.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable OPUS codec","description":"Adds an option to use the OPUS audio codec instead of the MP4A audio codec.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable OPUS codec","description":"Adds an options to enable the OPUS audio codec if the player response includes.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable debug logging","description":"Adds an option to enable debug logging.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable debug logging","description":"Adds an option to enable debug logging.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable external browser","description":"Adds an option to always open links in your browser instead of in the in-app-browser.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable gradient loading screen","description":"Adds an option to enable the gradient loading screen.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable landscape mode","description":"Adds an option to enable landscape mode when rotating the screen on phones.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable open links directly","description":"Adds an option to skip over redirection URLs in external links.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Flyout menu components","description":"Adds options to hide or change flyout menu components.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Force player buttons background","description":"Changes, at compile time, the dark background surrounding the video player controls.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"BackgroundColor","default":"?ytOverlayBackgroundMediumLight","values":{"Default":"?ytOverlayBackgroundMediumLight","Transparent":"@android:color/transparent","Opacity10":"#1a000000","Opacity20":"#33000000","Opacity30":"#4d000000","Opacity40":"#66000000","Opacity50":"#80000000","Opacity60":"#99000000","Opacity70":"#b3000000","Opacity80":"#cc000000","Opacity90":"#e6000000","Opacity100":"#ff000000"},"title":"Background color","description":"Specify a background color for player buttons using a hex color code. The first two symbols of the hex code represent the alpha channel, which is used to change the opacity.","required":false}]},{"name":"Force snackbar theme","description":"Force snackbar background color to match selected theme.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"CornerRadius","default":"8.0dip","values":null,"title":"Corner radius","description":"Specify a corner radius for the snackbar.","required":false},{"key":"BackgroundColor","default":"?ytChipBackground","values":{"Chip":"?ytChipBackground","Base":"?ytBaseBackground"},"title":"Background color","description":"Specify a background color for the snackbar. You can specify hex color.","required":false},{"key":"StrokeColor","default":"none","values":{"None":"none","Accent":"?attr/colorAccent","Inverted":"?attr/ytInvertedBackground"},"title":"Stroke color","description":"Specify a stroke color for the snackbar. You can specify hex color.","required":false}]},{"name":"Fullscreen components","description":"Adds options to hide or change components related to fullscreen.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"GmsCore support","description":"Allows patched Google apps to run without root and under a different package name by using GmsCore instead of Google Play Services.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":true,"options":[{"key":"GmsCoreVendorGroupId","default":"app.revanced","values":{"ReVanced":"app.revanced"},"title":"GmsCore vendor group ID","description":"The vendor\u0027s group ID for GmsCore.","required":true},{"key":"CheckGmsCore","default":true,"values":null,"title":"Check GmsCore","description":"Check if GmsCore is installed on the device and has battery optimizations disabled when the app starts. \n\nIf GmsCore is not installed the app will not work, so disabling this is not recommended.","required":true},{"key":"PackageNameYouTube","default":"anddea.youtube","values":{"Clone":"bill.youtube","Default":"anddea.youtube"},"title":"Package name of YouTube","description":"The name of the package to use in GmsCore support.","required":true},{"key":"PackageNameYouTubeMusic","default":"anddea.youtube.music","values":{"Clone":"bill.youtube.music","Default":"anddea.youtube.music"},"title":"Package name of YouTube Music","description":"The name of the package to use in GmsCore support.","required":true}]},{"name":"GmsCore support","description":"Allows patched Google apps to run without root and under a different package name by using GmsCore instead of Google Play Services.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":true,"options":[{"key":"GmsCoreVendorGroupId","default":"app.revanced","values":{"ReVanced":"app.revanced"},"title":"GmsCore vendor group ID","description":"The vendor\u0027s group ID for GmsCore.","required":true},{"key":"CheckGmsCore","default":true,"values":null,"title":"Check GmsCore","description":"Check if GmsCore is installed on the device and has battery optimizations disabled when the app starts. \n\nIf GmsCore is not installed the app will not work, so disabling this is not recommended.","required":true},{"key":"PackageNameYouTube","default":"anddea.youtube","values":{"Clone":"bill.youtube","Default":"anddea.youtube"},"title":"Package name of YouTube","description":"The name of the package to use in GmsCore support.","required":true},{"key":"PackageNameYouTubeMusic","default":"anddea.youtube.music","values":{"Clone":"bill.youtube.music","Default":"anddea.youtube.music"},"title":"Package name of YouTube Music","description":"The name of the package to use in GmsCore support.","required":true}]},{"name":"Hide Recently Visited shelf","description":"Adds an option to hide the Recently Visited shelf in the sidebar.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide Shorts dimming","description":"Removes, at compile time, the dimming effect at the top and bottom of Shorts videos.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Hide account components","description":"Adds options to hide components related to the account menu.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide action bar components","description":"Adds options to hide action bar components and replace the offline download button with an external download button.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide action buttons","description":"Adds options to hide action buttons under videos.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide ads","description":"Adds options to hide ads.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":true,"options":[]},{"name":"Hide ads","description":"Adds options to hide ads.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide ads","description":"Adds options to hide ads.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide comments components","description":"Adds options to hide components related to comments.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide feed components","description":"Adds options to hide components related to feeds.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide feed flyout menu","description":"Adds the ability to hide feed flyout menu components using a custom filter.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide layout components","description":"Adds options to hide general layout components.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide layout components","description":"Adds options to hide general layout components.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide navigation buttons","description":"Adds options to hide buttons in the navigation bar.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide overlay filter","description":"Removes, at compile time, the dark overlay that appears when player flyout menus are open.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Hide player buttons","description":"Adds options to hide buttons in the video player.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide player flyout menu","description":"Adds options to hide player flyout menu components.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide player overlay filter","description":"Removes, at compile time, the dark overlay that appears when single-tapping in the player.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Hide recommended communities shelf","description":"Adds an option to hide the recommended communities shelves in subreddits.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hook download actions","description":"Adds support to download videos with an external downloader app using the in-app download button.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Layout switch","description":"Adds an option to spoof the dpi in order to use a tablet or phone layout.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"MaterialYou","description":"Applies the MaterialYou theme for Android 12+ devices.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Miniplayer","description":"Adds options to change the in app minimized player, and if patching target 19.16+ adds options to use modern miniplayers.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Navigation bar components","description":"Adds options to hide or change components related to the navigation bar.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Navigation bar components","description":"Adds options to hide or change components related to the navigation bar.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Open links directly","description":"Adds an option to skip over redirection URLs in external links.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Open links externally","description":"Adds an option to always open links in your browser instead of in the in-app-browser.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Overlay buttons","description":"Adds options to display overlay buttons in the video player.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"IconType","default":"rounded","values":{"Bold":"bold","Rounded":"rounded","Thin":"thin"},"title":"Icon type","description":"The icon type.","required":true},{"key":"BottomMargin","default":"5.0dip","values":{"Wider":"10.0dip","Default":"5.0dip"},"title":"Bottom margin","description":"The bottom margin for the overlay buttons and timestamp.","required":true},{"key":"ChangeTopButtons","default":false,"values":null,"title":"Change top buttons","description":"Change the icons at the top of the player.","required":true}]},{"name":"Player components","description":"Adds options to hide or change components related to the player.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Player components","description":"Adds options to hide or change components related to the video player.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Premium icon","description":"Unlocks premium app icons.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove background playback restrictions","description":"Removes restrictions on background playback, including for kids videos.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove background playback restrictions","description":"Removes restrictions on background playback, including for music and kids videos.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove subreddit dialog","description":"Adds options to remove the NSFW community warning and notifications suggestion dialogs by dismissing them automatically.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove viewer discretion dialog","description":"Adds an option to remove the dialog that appears when opening a video that has been age-restricted by accepting it automatically. This does not bypass the age restriction.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove viewer discretion dialog","description":"Adds an option to remove the dialog that appears when opening a video that has been age-restricted by accepting it automatically. This does not bypass the age restriction.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Restore old style library shelf","description":"Adds an option to return the Library tab to the old style.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Return YouTube Dislike","description":"Adds an option to show the dislike count of songs using the Return YouTube Dislike API.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Return YouTube Dislike","description":"Adds an option to show the dislike count of videos using the Return YouTube Dislike API.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Sanitize sharing links","description":"Adds an option to remove tracking query parameters from URLs when sharing links.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Sanitize sharing links","description":"Adds an option to remove tracking query parameters from URLs when sharing links.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Sanitize sharing links","description":"Adds an option to remove tracking query parameters from URLs when sharing links.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Seekbar components","description":"Adds options to hide or change components related to the seekbar.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"CairoStartColor","default":"#ffff2791","values":null,"title":"Cairo start color","description":"Set Cairo start color for the seekbar.","required":false},{"key":"CairoEndColor","default":"#ffff0033","values":null,"title":"Cairo end color","description":"Set Cairo end color for the seekbar.","required":false}]},{"name":"Settings for Reddit","description":"Applies mandatory patches to implement ReVanced Extended settings into the application.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":true,"options":[{"key":"RVXSettingsMenuName","default":"ReVanced Extended","values":null,"title":"RVX settings menu name","description":"The name of the RVX settings menu.","required":true}]},{"name":"Settings for YouTube","description":"Applies mandatory patches to implement ReVanced Extended settings into the application.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":true,"options":[{"key":"InsertPosition","default":"About","values":{"Parent settings":"@string/parent_tools_key","General":"@string/general_key","Account":"@string/account_switcher_key","Data saving":"@string/data_saving_settings_key","Autoplay":"@string/auto_play_key","Video quality preferences":"@string/video_quality_settings_key","Background":"@string/offline_key","Watch on TV":"@string/pair_with_tv_key","Manage all history":"@string/history_key","Your data in YouTube":"@string/your_data_key","Privacy":"@string/privacy_key","History \u0026 privacy":"@string/privacy_key","Try experimental new features":"@string/premium_early_access_browse_page_key","Purchases and memberships":"@string/subscription_product_setting_key","Billing \u0026 payments":"@string/billing_and_payment_key","Billing and payments":"@string/billing_and_payment_key","Notifications":"@string/notification_key","Connected apps":"@string/connected_accounts_browse_page_key","Live chat":"@string/live_chat_key","Captions":"@string/captions_key","Accessibility":"@string/accessibility_settings_key","About":"@string/about_key"},"title":"Insert position","description":"The settings menu name that the RVX settings menu should be above.","required":true},{"key":"RVXSettingsMenuName","default":"ReVanced Extended","values":null,"title":"RVX settings menu name","description":"The name of the RVX settings menu.","required":true}]},{"name":"Settings for YouTube Music","description":"Applies mandatory patches to implement ReVanced Extended settings into the application.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":true,"options":[{"key":"RVXSettingsMenuName","default":"ReVanced Extended","values":null,"title":"RVX settings menu name","description":"The name of the RVX settings menu.","required":true}]},{"name":"Shorts components","description":"Adds options to hide or change components related to YouTube Shorts.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"SponsorBlock","description":"Adds options to enable and configure SponsorBlock, which can skip undesired video segments, such as non-music sections.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"SponsorBlock","description":"Adds options to enable and configure SponsorBlock, which can skip undesired video segments, such as sponsored content.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"OutlineIcon","default":true,"values":null,"title":"Outline icons","description":"Apply the outline icon.","required":true},{"key":"NewSegmentAlignment","default":"right","values":{"Right":"right","Left":"left"},"title":"New segment alignment","description":"Align new segment window.","required":true}]},{"name":"Spoof app version","description":"Adds options to spoof the YouTube Music client version. This can remove the radio mode restriction in Canadian regions or disable real-time lyrics.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Spoof app version","description":"Adds options to spoof the YouTube client version. This can be used to restore old UI elements and features.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Spoof streaming data","description":"Adds options to spoof the streaming data to allow video playback.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Spoof watch history","description":"Adds an option to change the domain of the watch history or check its status.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Swipe controls","description":"Adds options for controlling volume and brightness with swiping, and whether to enter fullscreen when swiping down below the player.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Theme","description":"Changes the app\u0027s theme to the values specified in options.json.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"DarkThemeBackgroundColor","default":"@android:color/black","values":{"Amoled Black":"@android:color/black","Catppuccin (Mocha)":"#FF181825","Dark Pink":"#FF290025","Dark Blue":"#FF001029","Dark Green":"#FF002905","Dark Yellow":"#FF282900","Dark Orange":"#FF291800","Dark Red":"#FF290000"},"title":"Dark theme background color","description":"Can be a hex color (#AARRGGBB) or a color resource reference.","required":true},{"key":"LightThemeBackgroundColor","default":"@android:color/white","values":{"White":"@android:color/white","Catppuccin (Latte)":"#FFE6E9EF","Light Pink":"#FFFCCFF3","Light Blue":"#FFD1E0FF","Light Green":"#FFCCFFCC","Light Yellow":"#FFFDFFCC","Light Orange":"#FFFFE6CC","Light Red":"#FFFFD6D6"},"title":"Light theme background color","description":"Can be a hex color (#AARRGGBB) or a color resource reference.","required":true}]},{"name":"Toolbar components","description":"Adds options to hide or change components located on the toolbar, such as toolbar buttons, search bar, and header.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Translations","description":"Adds Crowdin translations for YouTube Music.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"CustomLanguage","default":"","values":null,"title":"Custom language file","description":"The file path to the strings.xml file.\nPlease note that applying the strings.xml file will overwrite all existing language translations.","required":false},{"key":"SelectedLanguages","default":"bg-rBG, bn, cs-rCZ, el-rGR, es-rES, fr-rFR, hu-rHU, id-rID, in, it-rIT, ja-rJP, ko-rKR, nl-rNL, pl-rPL, pt-rBR, ro-rRO, ru-rRU, tr-rTR, uk-rUA, vi-rVN, zh-rCN, zh-rTW","values":null,"title":"Selected RVX languages","description":"Selected RVX languages that will be added.","required":false},{"key":"SelectedAppLanguages","default":"af, am, ar, ar-rXB, as, az, b+es+419, b+sr+Latn, be, bg, bn, bs, ca, cs, da, de, el, en-rAU, en-rCA, en-rGB, en-rIN, en-rXA, en-rXC, es, es-rUS, et, eu, fa, fi, fr, fr-rCA, gl, gu, hi, hr, hu, hy, id, in, is, it, iw, ja, ka, kk, km, kn, ko, ky, lo, lt, lv, mk, ml, mn, mr, ms, my, nb, ne, nl, no, or, pa, pl, pt, pt-rBR, pt-rPT, ro, ru, si, sk, sl, sq, sr, sv, sw, ta, te, th, tl, tr, uk, ur, uz, vi, zh, zh-rCN, zh-rHK, zh-rTW, zu","values":null,"title":"Selected app languages","description":"Selected app languages that will be kept, languages that are not in the list will be removed from the app.","required":false}]},{"name":"Translations","description":"Add Crowdin translations for YouTube.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"CustomLanguage","default":"","values":null,"title":"Custom language file","description":"The file path to the strings.xml file.\nPlease note that applying the strings.xml file will overwrite all existing language translations.","required":false},{"key":"SelectedLanguages","default":"ar, bg-rBG, bn, de-rDE, el-rGR, es-rES, fi-rFI, fr-rFR, hu-rHU, id-rID, in, it-rIT, ja-rJP, ko-rKR, pl-rPL, pt-rBR, ru-rRU, tr-rTR, uk-rUA, vi-rVN, zh-rCN, zh-rTW","values":null,"title":"Selected RVX languages","description":"Selected RVX languages that will be added.","required":false},{"key":"SelectedAppLanguages","default":"af, am, ar, ar-rXB, as, az, b+es+419, b+sr+Latn, be, bg, bn, bs, ca, cs, da, de, el, en-rAU, en-rCA, en-rGB, en-rIN, en-rXA, en-rXC, es, es-rUS, et, eu, fa, fi, fr, fr-rCA, gl, gu, hi, hr, hu, hy, id, in, is, it, iw, ja, ka, kk, km, kn, ko, ky, lo, lt, lv, mk, ml, mn, mr, ms, my, nb, ne, nl, no, or, pa, pl, pt, pt-rBR, pt-rPT, ro, ru, si, sk, sl, sq, sr, sv, sw, ta, te, th, tl, tr, uk, ur, uz, vi, zh, zh-rCN, zh-rHK, zh-rTW, zu","values":null,"title":"Selected app languages","description":"Selected app languages that will be kept, languages that are not in the list will be removed from the app.","required":false}]},{"name":"Video playback","description":"Adds options to customize settings related to video playback, such as default video quality and playback speed.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Video playback","description":"Adds options to customize settings related to video playback, such as default video quality and playback speed.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Visual preferences icons","description":"Adds icons to specific preferences in the settings.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.58","6.33.52","6.42.55","6.51.53","7.16.52"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"ExtendedIcon","default":"Extension","values":{"Custom branding icon":"custom_branding_icon","Extension":"extension","Gear":"gear","ReVanced":"revanced","ReVanced Colored":"revanced_colored"},"title":"Extended icon","description":"Apply different icons for Extended preference.","required":false}]},{"name":"Visual preferences icons","description":"Adds icons to specific preferences in the settings.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"ExtendedIcon","default":"Extension","values":{"Custom branding icon":"custom_branding_icon","Extension":"extension","Gear":"gear","ReVanced":"revanced","ReVanced Colored":"revanced_colored"},"title":"RVX settings menu icon","description":"The icon for the RVX settings menu.","required":true}]}] \ No newline at end of file +[{"name":"Alternative thumbnails","description":"Adds options to replace video thumbnails using the DeArrow API or image captures from the video.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Ambient mode control","description":"Adds options to disable Ambient mode and to bypass Ambient mode restrictions.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Amoled","description":"Applies a pure black theme to some components.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Bitrate default value","description":"Sets the audio quality to \u0027Always High\u0027 when you first install the app.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Bypass image region restrictions","description":"Adds an option to use a different host for static images, so that images blocked in some countries can be received.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Bypass image region restrictions","description":"Adds an option to use a different host for static images, so that images blocked in some countries can be received.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Certificate spoof","description":"Enables YouTube Music to work with Android Auto by spoofing the YouTube Music certificate.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Change package name","description":"Changes the package name for Reddit to the name specified in options.json.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":false,"requiresIntegrations":false,"options":[{"key":"PackageNameReddit","default":"com.reddit.frontpage","values":{"Clone":"com.reddit.frontpage.revanced","Default":"com.reddit.frontpage.rvx","Original":"com.reddit.frontpage"},"title":"Package name of Reddit","description":"The name of the package to rename the app to.","required":true}]},{"name":"Change player flyout menu toggles","description":"Adds an option to use text toggles instead of switch toggles within the additional settings menu.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Change share sheet","description":"Add option to change from in-app share sheet to system share sheet.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Change share sheet","description":"Add option to change from in-app share sheet to system share sheet.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Change start page","description":"Adds an option to set which page the app opens in instead of the homepage.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Change start page","description":"Adds an option to set which page the app opens in instead of the homepage.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Change version code","description":"Changes the version code of the app to the value specified in options.json. Except when mounting, this can prevent app stores from updating the app and allow the app to be installed over an existing installation that has a higher version code. By default, the highest version code is set.","compatiblePackages":null,"use":false,"requiresIntegrations":false,"options":[{"key":"ChangeVersionCode","default":false,"values":null,"title":"Change version code","description":"Changes the version code of the app.","required":true},{"key":"VersionCode","default":"2147483647","values":null,"title":"Version code","description":"The version code to use. (1 ~ 2147483647)","required":true}]},{"name":"Custom Shorts action buttons","description":"Changes, at compile time, the icon of the action buttons of the Shorts player.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"IconType","default":"round","values":{"Cairo":"round","Outline":"outline","OutlineCircle":"outlinecircle","Round":"round","YouTube":"youtube","YouTubeOutline":"youtubeoutline"},"title":"Shorts icon style ","description":"The style of the icons for the action buttons in the Shorts player.","required":true}]},{"name":"Custom branding icon for YouTube","description":"Changes the YouTube app icon to the icon specified in options.json.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":false,"requiresIntegrations":false,"options":[{"key":"AppIcon","default":"Xisr Yellow","values":{"AFN Blue":"afn_blue","AFN Red":"afn_red","MMT":"mmt","MMT Blue":"mmt_blue","MMT Green":"mmt_green","MMT Orange":"mmt_orange","MMT Pink":"mmt_pink","MMT Turquoise":"mmt_turquoise","MMT Yellow":"mmt_yellow","Revancify Blue":"revancify_blue","Revancify Red":"revancify_red","Vanced Black":"vanced_black","Vanced Light":"vanced_light","Xisr Yellow":"xisr_yellow","YouTube":"youtube"},"title":"App icon","description":"The icon to apply to the app.\n\nIf a path to a folder is provided, the folder must contain the following folders:\n\n- mipmap-xxxhdpi\n- mipmap-xxhdpi\n- mipmap-xhdpi\n- mipmap-hdpi\n- mipmap-mdpi\n\nEach of these folders must contain the following files:\n\n- adaptiveproduct_youtube_background_color_108.png\n- adaptiveproduct_youtube_foreground_color_108.png\n- ic_launcher.png\n- ic_launcher_round.png","required":true},{"key":"ChangeHeader","default":true,"values":null,"title":"Change header","description":"Apply the custom branding icon to the header.","required":true},{"key":"CustomHeader","default":"","values":null,"title":"Custom header","description":"The header to apply to the app.\n\nIf a path to a folder is provided, the folder must contain one or more of the following folders, depending on the DPI of the device:\n\n- drawable-xxxhdpi\n- drawable-xxhdpi\n- drawable-xhdpi\n- drawable-hdpi\n- drawable-mdpi\n\nEach of the folders must contain all of the following files:\n\n- yt_premium_wordmark_header_dark.png\n- yt_premium_wordmark_header_light.png\n- yt_wordmark_header_dark.png\n- yt_wordmark_header_light.png\n\nThe image dimensions must be as follows:\n- drawable-xxxhdpi: 512px x 192px\n- drawable-xxhdpi: 387px x 144px\n- drawable-xhdpi: 258px x 96px\n- drawable-hdpi: 194px x 72px\n- drawable-mdpi: 129px x 48px","required":true},{"key":"ChangeSplashIcon","default":true,"values":null,"title":"Change splash icons","description":"Apply the custom branding icon to the splash screen.","required":true},{"key":"RestoreOldSplashAnimation","default":true,"values":null,"title":"Restore old splash animation","description":"Restore the old style splash animation.","required":true}]},{"name":"Custom branding icon for YouTube Music","description":"Changes the YouTube Music app icon to the icon specified in options.json.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":false,"requiresIntegrations":false,"options":[{"key":"AppIcon","default":"Xisr Yellow","values":{"AFN Blue":"afn_blue","AFN Red":"afn_red","MMT":"mmt","MMT Blue":"mmt_blue","MMT Green":"mmt_green","MMT Orange":"mmt_orange","MMT Pink":"mmt_pink","MMT Turquoise":"mmt_turquoise","MMT Yellow":"mmt_yellow","Revancify Blue":"revancify_blue","Revancify Red":"revancify_red","Vanced Black":"vanced_black","Vanced Light":"vanced_light","Xisr Yellow":"xisr_yellow","YouTube Music":"youtube_music"},"title":"App icon","description":"The icon to apply to the app.\n\nIf a path to a folder is provided, the folder must contain the following folders:\n\n- mipmap-xxxhdpi\n- mipmap-xxhdpi\n- mipmap-xhdpi\n- mipmap-hdpi\n- mipmap-mdpi\n\nEach of these folders must contain the following files:\n\n- adaptiveproduct_youtube_music_background_color_108.png\n- adaptiveproduct_youtube_music_foreground_color_108.png\n- ic_launcher_release.png","required":true},{"key":"ChangeHeader","default":true,"values":null,"title":"Change header","description":"Apply the custom branding icon to the header.","required":true},{"key":"ChangeSplashIcon","default":true,"values":null,"title":"Change splash icons","description":"Apply the custom branding icon to the splash screen.","required":true},{"key":"RestoreOldSplashIcon","default":false,"values":null,"title":"Restore old splash icon","description":"Restore the old style splash icon.\n\nIf you enable both the old style splash icon and the Cairo splash animation,\n\nOld style splash icon will appear first and then the Cairo splash animation will start.","required":true}]},{"name":"Custom branding name for Reddit","description":"Renames the Reddit app to the name specified in options.json.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":false,"requiresIntegrations":false,"options":[{"key":"AppName","default":"Reddit","values":{"Default":"RVX Reddit","Original":"Reddit"},"title":"App name","description":"The name of the app.","required":true}]},{"name":"Custom branding name for YouTube","description":"Renames the YouTube app to the name specified in options.json.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":false,"requiresIntegrations":false,"options":[{"key":"AppName","default":"RVX","values":{"ReVanced Extended":"ReVanced Extended","RVX":"RVX","YouTube RVX":"YouTube RVX","YouTube":"YouTube"},"title":"App name","description":"The name of the app.","required":true}]},{"name":"Custom branding name for YouTube Music","description":"Renames the YouTube Music app to the name specified in options.json.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":false,"requiresIntegrations":false,"options":[{"key":"AppNameNotification","default":"RVX Music","values":{"ReVanced Extended Music":"ReVanced Extended Music","RVX Music":"RVX Music","YouTube Music":"YouTube Music","YT Music":"YT Music"},"title":"App name in notification panel","description":"The name of the app as it appears in the notification panel.","required":true},{"key":"AppNameLauncher","default":"RVX Music","values":{"ReVanced Extended Music":"ReVanced Extended Music","RVX Music":"RVX Music","YouTube Music":"YouTube Music","YT Music":"YT Music"},"title":"App name in launcher","description":"The name of the app as it appears in the launcher.","required":true}]},{"name":"Custom double tap length","description":"Adds Double-tap to seek values that are specified in options.json.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"DoubleTapLengthArrays","default":"3, 5, 10, 15, 20, 30, 60, 120, 180","values":null,"title":"Double-tap to seek values","description":"A list of custom Double-tap to seek lengths to be added, separated by commas.","required":true}]},{"name":"Custom header for YouTube Music","description":"Applies a custom header in the top left corner within the app.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":false,"requiresIntegrations":false,"options":[{"key":"CustomHeader","default":"custom_branding_icon","values":{"Custom branding icon":"custom_branding_icon"},"title":"Custom header","description":"The header to apply to the app.\n\nPatch option \u0027Custom branding icon\u0027 applies only when:\n\n1. Patch \u0027Custom branding icon for YouTube Music\u0027 is included.\n2. Patch option for \u0027Custom branding icon for YouTube Music\u0027 is selected from the preset.\n\nIf a path to a folder is provided, the folder must contain one or more of the following folders, depending on the DPI of the device:\n\n- drawable-xxxhdpi\n- drawable-xxhdpi\n- drawable-xhdpi\n- drawable-hdpi\n- drawable-mdpi\n\nEach of the folders must contain all of the following files:\n\n- action_bar_logo.png\n- logo_music.png\n- ytm_logo.png\n\nThe image \u0027action_bar_logo.png\u0027 dimensions must be as follows:\n\n- drawable-xxxhdpi: 320px x 96px\n- drawable-xxhdpi: 240px x 72px\n- drawable-xhdpi: 160px x 48px\n- drawable-hdpi: 121px x 36px\n- drawable-mdpi: 80px x 24px\n\nThe image \u0027logo_music.png\u0027 dimensions must be as follows:\n\n- drawable-xxxhdpi: 576px x 200px\n- drawable-xxhdpi: 432px x 150px\n- drawable-xhdpi: 288px x 100px\n- drawable-hdpi: 217px x 76px\n- drawable-mdpi: 144px x 50px\n\nThe image \u0027ytm_logo.png\u0027 dimensions must be as follows:\n\n- drawable-xxxhdpi: 412px x 144px\n- drawable-xxhdpi: 309px x 108px\n- drawable-xhdpi: 206px x 72px\n- drawable-hdpi: 155px x 54px\n- drawable-mdpi: 103px x 36px","required":true}]},{"name":"Description components","description":"Adds options to hide and disable description components.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable Cairo splash animation","description":"Adds an option to disable Cairo splash animation.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["7.06.54","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable QUIC protocol","description":"Adds an option to disable CronetEngine\u0027s QUIC protocol.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable auto audio tracks","description":"Adds an option to disable audio tracks from being automatically enabled.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable auto captions","description":"Adds an option to disable captions from being automatically enabled.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable auto captions","description":"Adds an option to disable captions from being automatically enabled.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable dislike redirection","description":"Adds an option to disable redirection to the next track when clicking the Dislike button.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable haptic feedback","description":"Adds options to disable haptic feedback when swiping in the video player.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable resuming Shorts on startup","description":"Adds an option to disable the Shorts player from resuming on app startup when Shorts were last being watched.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable screenshot popup","description":"Adds an option to disable the popup that appears when taking a screenshot.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Disable splash animation","description":"Adds an option to disable the splash animation on app startup.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable OPUS codec","description":"Adds an option to use the OPUS audio codec instead of the MP4A audio codec.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable OPUS codec","description":"Adds an options to enable the OPUS audio codec if the player response includes.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable debug logging","description":"Adds an option to enable debug logging.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable debug logging","description":"Adds an option to enable debug logging.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable external browser","description":"Adds an option to always open links in your browser instead of in the in-app-browser.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable gradient loading screen","description":"Adds an option to enable the gradient loading screen.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable landscape mode","description":"Adds an option to enable landscape mode when rotating the screen on phones.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Enable open links directly","description":"Adds an option to skip over redirection URLs in external links.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Flyout menu components","description":"Adds options to hide or change flyout menu components.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Force player buttons background","description":"Changes, at compile time, the dark background surrounding the video player controls.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"BackgroundColor","default":"?ytOverlayBackgroundMediumLight","values":{"Default":"?ytOverlayBackgroundMediumLight","Transparent":"@android:color/transparent","Opacity10":"#1a000000","Opacity20":"#33000000","Opacity30":"#4d000000","Opacity40":"#66000000","Opacity50":"#80000000","Opacity60":"#99000000","Opacity70":"#b3000000","Opacity80":"#cc000000","Opacity90":"#e6000000","Opacity100":"#ff000000"},"title":"Background color","description":"Specify a background color for player buttons using a hex color code. The first two symbols of the hex code represent the alpha channel, which is used to change the opacity.","required":false}]},{"name":"Force snackbar theme","description":"Force snackbar background color to match selected theme.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"CornerRadius","default":"8.0dip","values":null,"title":"Corner radius","description":"Specify a corner radius for the snackbar.","required":false},{"key":"BackgroundColor","default":"?ytChipBackground","values":{"Chip":"?ytChipBackground","Base":"?ytBaseBackground"},"title":"Background color","description":"Specify a background color for the snackbar. You can specify hex color.","required":false},{"key":"StrokeColor","default":"none","values":{"None":"none","Accent":"?attr/colorAccent","Inverted":"?attr/ytInvertedBackground"},"title":"Stroke color","description":"Specify a stroke color for the snackbar. You can specify hex color.","required":false}]},{"name":"Fullscreen components","description":"Adds options to hide or change components related to fullscreen.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"GmsCore support","description":"Allows patched Google apps to run without root and under a different package name by using GmsCore instead of Google Play Services.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":true,"options":[{"key":"GmsCoreVendorGroupId","default":"app.revanced","values":{"ReVanced":"app.revanced"},"title":"GmsCore vendor group ID","description":"The vendor\u0027s group ID for GmsCore.","required":true},{"key":"CheckGmsCore","default":true,"values":null,"title":"Check GmsCore","description":"Check if GmsCore is installed on the device and has battery optimizations disabled when the app starts. \n\nIf GmsCore is not installed the app will not work, so disabling this is not recommended.","required":true},{"key":"PackageNameYouTube","default":"anddea.youtube","values":{"Clone":"bill.youtube","Default":"anddea.youtube"},"title":"Package name of YouTube","description":"The name of the package to use in GmsCore support.","required":true},{"key":"PackageNameYouTubeMusic","default":"anddea.youtube.music","values":{"Clone":"bill.youtube.music","Default":"anddea.youtube.music"},"title":"Package name of YouTube Music","description":"The name of the package to use in GmsCore support.","required":true}]},{"name":"GmsCore support","description":"Allows patched Google apps to run without root and under a different package name by using GmsCore instead of Google Play Services.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":true,"options":[{"key":"GmsCoreVendorGroupId","default":"app.revanced","values":{"ReVanced":"app.revanced"},"title":"GmsCore vendor group ID","description":"The vendor\u0027s group ID for GmsCore.","required":true},{"key":"CheckGmsCore","default":true,"values":null,"title":"Check GmsCore","description":"Check if GmsCore is installed on the device and has battery optimizations disabled when the app starts. \n\nIf GmsCore is not installed the app will not work, so disabling this is not recommended.","required":true},{"key":"PackageNameYouTube","default":"anddea.youtube","values":{"Clone":"bill.youtube","Default":"anddea.youtube"},"title":"Package name of YouTube","description":"The name of the package to use in GmsCore support.","required":true},{"key":"PackageNameYouTubeMusic","default":"anddea.youtube.music","values":{"Clone":"bill.youtube.music","Default":"anddea.youtube.music"},"title":"Package name of YouTube Music","description":"The name of the package to use in GmsCore support.","required":true}]},{"name":"Hide Recently Visited shelf","description":"Adds an option to hide the Recently Visited shelf in the sidebar.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide Shorts dimming","description":"Removes, at compile time, the dimming effect at the top and bottom of Shorts videos.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Hide account components","description":"Adds options to hide components related to the account menu.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide action bar components","description":"Adds options to hide action bar components and replace the offline download button with an external download button.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide action buttons","description":"Adds options to hide action buttons under videos.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide ads","description":"Adds options to hide ads.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":true,"options":[]},{"name":"Hide ads","description":"Adds options to hide ads.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide ads","description":"Adds options to hide ads.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide comments components","description":"Adds options to hide components related to comments.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide feed components","description":"Adds options to hide components related to feeds.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide feed flyout menu","description":"Adds the ability to hide feed flyout menu components using a custom filter.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide layout components","description":"Adds options to hide general layout components.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide layout components","description":"Adds options to hide general layout components.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide navigation buttons","description":"Adds options to hide buttons in the navigation bar.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide overlay filter","description":"Removes, at compile time, the dark overlay that appears when player flyout menus are open.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Hide player buttons","description":"Adds options to hide buttons in the video player.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide player flyout menu","description":"Adds options to hide player flyout menu components.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide player overlay filter","description":"Removes, at compile time, the dark overlay that appears when single-tapping in the player.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Hide recommended communities shelf","description":"Adds an option to hide the recommended communities shelves in subreddits.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hide shortcuts","description":"Remove, at compile time, the app shortcuts that appears when app icon is long pressed.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":false,"requiresIntegrations":false,"options":[{"key":"Explore","default":false,"values":null,"title":"Hide Explore","description":"Hide Explore from shortcuts.","required":true},{"key":"Subscriptions","default":false,"values":null,"title":"Hide Subscriptions","description":"Hide Subscriptions from shortcuts.","required":true},{"key":"Search","default":false,"values":null,"title":"Hide Search","description":"Hide Search from shortcuts.","required":true},{"key":"Shorts","default":true,"values":null,"title":"Hide Shorts","description":"Hide Shorts from shortcuts.","required":true}]},{"name":"Hook YouTube Music actions","description":"Adds support for opening music in RVX Music using the in-app YouTube Music button.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Hook download actions","description":"Adds support to download videos with an external downloader app using the in-app download button.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Layout switch","description":"Adds an option to spoof the dpi in order to use a tablet or phone layout.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"MaterialYou","description":"Applies the MaterialYou theme for Android 12+ devices.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":false,"requiresIntegrations":false,"options":[]},{"name":"Miniplayer","description":"Adds options to change the in app minimized player, and if patching target 19.16+ adds options to use modern miniplayers.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Navigation bar components","description":"Adds options to hide or change components related to the navigation bar.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Navigation bar components","description":"Adds options to hide or change components related to the navigation bar.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Open links directly","description":"Adds an option to skip over redirection URLs in external links.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Open links externally","description":"Adds an option to always open links in your browser instead of in the in-app-browser.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Overlay buttons","description":"Adds options to display overlay buttons in the video player.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"IconType","default":"rounded","values":{"Bold":"bold","Rounded":"rounded","Thin":"thin"},"title":"Icon type","description":"The icon type.","required":true},{"key":"BottomMargin","default":"5.0dip","values":{"Wider":"10.0dip","Default":"5.0dip"},"title":"Bottom margin","description":"The bottom margin for the overlay buttons and timestamp.","required":true},{"key":"ChangeTopButtons","default":false,"values":null,"title":"Change top buttons","description":"Change the icons at the top of the player.","required":true}]},{"name":"Player components","description":"Adds options to hide or change components related to the player.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Player components","description":"Adds options to hide or change components related to the video player.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Premium icon","description":"Unlocks premium app icons.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove background playback restrictions","description":"Removes restrictions on background playback, including for kids videos.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove background playback restrictions","description":"Removes restrictions on background playback, including for music and kids videos.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove subreddit dialog","description":"Adds options to remove the NSFW community warning and notifications suggestion dialogs by dismissing them automatically.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove viewer discretion dialog","description":"Adds an option to remove the dialog that appears when opening a video that has been age-restricted by accepting it automatically. This does not bypass the age restriction.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Remove viewer discretion dialog","description":"Adds an option to remove the dialog that appears when opening a video that has been age-restricted by accepting it automatically. This does not bypass the age restriction.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Restore old style library shelf","description":"Adds an option to return the Library tab to the old style.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Return YouTube Dislike","description":"Adds an option to show the dislike count of songs using the Return YouTube Dislike API.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Return YouTube Dislike","description":"Adds an option to show the dislike count of videos using the Return YouTube Dislike API.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Sanitize sharing links","description":"Adds an option to remove tracking query parameters from URLs when sharing links.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Sanitize sharing links","description":"Adds an option to remove tracking query parameters from URLs when sharing links.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Sanitize sharing links","description":"Adds an option to remove tracking query parameters from URLs when sharing links.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Seekbar components","description":"Adds options to hide or change components related to the seekbar.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"CairoStartColor","default":"#ffff2791","values":null,"title":"Cairo start color","description":"Set Cairo start color for the seekbar.","required":false},{"key":"CairoEndColor","default":"#ffff0033","values":null,"title":"Cairo end color","description":"Set Cairo end color for the seekbar.","required":false}]},{"name":"Settings for Reddit","description":"Applies mandatory patches to implement ReVanced Extended settings into the application.","compatiblePackages":[{"name":"com.reddit.frontpage","versions":["2023.12.0","2024.17.0"]}],"use":true,"requiresIntegrations":true,"options":[{"key":"RVXSettingsMenuName","default":"ReVanced Extended","values":null,"title":"RVX settings menu name","description":"The name of the RVX settings menu.","required":true}]},{"name":"Settings for YouTube","description":"Applies mandatory patches to implement ReVanced Extended settings into the application.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":true,"options":[{"key":"InsertPosition","default":"About","values":{"Parent settings":"@string/parent_tools_key","General":"@string/general_key","Account":"@string/account_switcher_key","Data saving":"@string/data_saving_settings_key","Autoplay":"@string/auto_play_key","Video quality preferences":"@string/video_quality_settings_key","Background":"@string/offline_key","Watch on TV":"@string/pair_with_tv_key","Manage all history":"@string/history_key","Your data in YouTube":"@string/your_data_key","Privacy":"@string/privacy_key","History \u0026 privacy":"@string/privacy_key","Try experimental new features":"@string/premium_early_access_browse_page_key","Purchases and memberships":"@string/subscription_product_setting_key","Billing \u0026 payments":"@string/billing_and_payment_key","Billing and payments":"@string/billing_and_payment_key","Notifications":"@string/notification_key","Connected apps":"@string/connected_accounts_browse_page_key","Live chat":"@string/live_chat_key","Captions":"@string/captions_key","Accessibility":"@string/accessibility_settings_key","About":"@string/about_key"},"title":"Insert position","description":"The settings menu name that the RVX settings menu should be above.","required":true},{"key":"RVXSettingsMenuName","default":"ReVanced Extended","values":null,"title":"RVX settings menu name","description":"The name of the RVX settings menu.","required":true}]},{"name":"Settings for YouTube Music","description":"Applies mandatory patches to implement ReVanced Extended settings into the application.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":true,"options":[{"key":"RVXSettingsMenuName","default":"ReVanced Extended","values":null,"title":"RVX settings menu name","description":"The name of the RVX settings menu.","required":true}]},{"name":"Shorts components","description":"Adds options to hide or change components related to YouTube Shorts.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"SponsorBlock","description":"Adds options to enable and configure SponsorBlock, which can skip undesired video segments, such as non-music sections.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"SponsorBlock","description":"Adds options to enable and configure SponsorBlock, which can skip undesired video segments, such as sponsored content.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"OutlineIcon","default":true,"values":null,"title":"Outline icons","description":"Apply the outline icon.","required":true},{"key":"NewSegmentAlignment","default":"right","values":{"Right":"right","Left":"left"},"title":"New segment alignment","description":"Align new segment window.","required":true}]},{"name":"Spoof app version","description":"Adds options to spoof the YouTube Music client version. This can remove the radio mode restriction in Canadian regions or disable real-time lyrics.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Spoof app version","description":"Adds options to spoof the YouTube client version. This can be used to restore old UI elements and features.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Spoof streaming data","description":"Adds options to spoof the streaming data to allow video playback.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Spoof watch history","description":"Adds an option to change the domain of the watch history or check its status.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Swipe controls","description":"Adds options for controlling volume and brightness with swiping, and whether to enter fullscreen when swiping down below the player.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Theme","description":"Changes the app\u0027s theme to the values specified in options.json.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"DarkThemeBackgroundColor","default":"@android:color/black","values":{"Amoled Black":"@android:color/black","Catppuccin (Mocha)":"#FF181825","Dark Pink":"#FF290025","Dark Blue":"#FF001029","Dark Green":"#FF002905","Dark Yellow":"#FF282900","Dark Orange":"#FF291800","Dark Red":"#FF290000"},"title":"Dark theme background color","description":"Can be a hex color (#AARRGGBB) or a color resource reference.","required":true},{"key":"LightThemeBackgroundColor","default":"@android:color/white","values":{"White":"@android:color/white","Catppuccin (Latte)":"#FFE6E9EF","Light Pink":"#FFFCCFF3","Light Blue":"#FFD1E0FF","Light Green":"#FFCCFFCC","Light Yellow":"#FFFDFFCC","Light Orange":"#FFFFE6CC","Light Red":"#FFFFD6D6"},"title":"Light theme background color","description":"Can be a hex color (#AARRGGBB) or a color resource reference.","required":true}]},{"name":"Toolbar components","description":"Adds options to hide or change components located on the toolbar, such as toolbar buttons, search bar, and header.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Translations","description":"Adds Crowdin translations for YouTube Music.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"CustomLanguage","default":"","values":null,"title":"Custom language file","description":"The file path to the strings.xml file.\nPlease note that applying the strings.xml file will overwrite all existing language translations.","required":false},{"key":"SelectedLanguages","default":"bg-rBG, bn, cs-rCZ, el-rGR, es-rES, fr-rFR, hu-rHU, id-rID, in, it-rIT, ja-rJP, ko-rKR, nl-rNL, pl-rPL, pt-rBR, ro-rRO, ru-rRU, tr-rTR, uk-rUA, vi-rVN, zh-rCN, zh-rTW","values":null,"title":"Selected RVX languages","description":"Selected RVX languages that will be added.","required":false},{"key":"SelectedAppLanguages","default":"af, am, ar, ar-rXB, as, az, b+es+419, b+sr+Latn, be, bg, bn, bs, ca, cs, da, de, el, en-rAU, en-rCA, en-rGB, en-rIN, en-rXA, en-rXC, es, es-rUS, et, eu, fa, fi, fr, fr-rCA, gl, gu, hi, hr, hu, hy, id, in, is, it, iw, ja, ka, kk, km, kn, ko, ky, lo, lt, lv, mk, ml, mn, mr, ms, my, nb, ne, nl, no, or, pa, pl, pt, pt-rBR, pt-rPT, ro, ru, si, sk, sl, sq, sr, sv, sw, ta, te, th, tl, tr, uk, ur, uz, vi, zh, zh-rCN, zh-rHK, zh-rTW, zu","values":null,"title":"Selected app languages","description":"Selected app languages that will be kept, languages that are not in the list will be removed from the app.","required":false}]},{"name":"Translations","description":"Add Crowdin translations for YouTube.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"CustomLanguage","default":"","values":null,"title":"Custom language file","description":"The file path to the strings.xml file.\nPlease note that applying the strings.xml file will overwrite all existing language translations.","required":false},{"key":"SelectedLanguages","default":"ar, bg-rBG, bn, de-rDE, el-rGR, es-rES, fi-rFI, fr-rFR, hu-rHU, id-rID, in, it-rIT, ja-rJP, ko-rKR, pl-rPL, pt-rBR, ru-rRU, tr-rTR, uk-rUA, vi-rVN, zh-rCN, zh-rTW","values":null,"title":"Selected RVX languages","description":"Selected RVX languages that will be added.","required":false},{"key":"SelectedAppLanguages","default":"af, am, ar, ar-rXB, as, az, b+es+419, b+sr+Latn, be, bg, bn, bs, ca, cs, da, de, el, en-rAU, en-rCA, en-rGB, en-rIN, en-rXA, en-rXC, es, es-rUS, et, eu, fa, fi, fr, fr-rCA, gl, gu, hi, hr, hu, hy, id, in, is, it, iw, ja, ka, kk, km, kn, ko, ky, lo, lt, lv, mk, ml, mn, mr, ms, my, nb, ne, nl, no, or, pa, pl, pt, pt-rBR, pt-rPT, ro, ru, si, sk, sl, sq, sr, sv, sw, ta, te, th, tl, tr, uk, ur, uz, vi, zh, zh-rCN, zh-rHK, zh-rTW, zu","values":null,"title":"Selected app languages","description":"Selected app languages that will be kept, languages that are not in the list will be removed from the app.","required":false}]},{"name":"Video playback","description":"Adds options to customize settings related to video playback, such as default video quality and playback speed.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Video playback","description":"Adds options to customize settings related to video playback, such as default video quality and playback speed.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[]},{"name":"Visual preferences icons","description":"Adds icons to specific preferences in the settings.","compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["6.20.51","6.29.59","6.42.55","6.51.53","7.16.53"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"ExtendedIcon","default":"Extension","values":{"Custom branding icon":"custom_branding_icon","Extension":"extension","Gear":"gear","ReVanced":"revanced","ReVanced Colored":"revanced_colored"},"title":"Extended icon","description":"Apply different icons for Extended preference.","required":false}]},{"name":"Visual preferences icons","description":"Adds icons to specific preferences in the settings.","compatiblePackages":[{"name":"com.google.android.youtube","versions":["18.29.38","18.33.40","18.38.44","18.48.39","19.05.36","19.16.39"]}],"use":true,"requiresIntegrations":false,"options":[{"key":"ExtendedIcon","default":"Extension","values":{"Custom branding icon":"custom_branding_icon","Extension":"extension","Gear":"gear","ReVanced":"revanced","ReVanced Colored":"revanced_colored"},"title":"RVX settings menu icon","description":"The icon for the RVX settings menu.","required":true}]}] \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/account/components/AccountComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/music/account/components/AccountComponentsPatch.kt index 9b4288ad1..294d02e12 100644 --- a/src/main/kotlin/app/revanced/patches/music/account/components/AccountComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/account/components/AccountComponentsPatch.kt @@ -14,12 +14,14 @@ import app.revanced.patches.music.utils.integrations.Constants.ACCOUNT_CLASS_DES import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getTargetIndexWithReferenceOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode 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.reference.MethodReference @Suppress("unused") object AccountComponentsPatch : BaseBytecodePatch( @@ -43,8 +45,14 @@ object AccountComponentsPatch : BaseBytecodePatch( MenuEntryFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val textIndex = getTargetIndexWithMethodReferenceNameOrThrow("setText") - val viewIndex = getTargetIndexWithMethodReferenceNameOrThrow("addView") + val textIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setText" + } + val viewIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "addView" + } val textRegister = getInstruction(textIndex).registerD val viewRegister = getInstruction(viewIndex).registerD @@ -64,9 +72,14 @@ object AccountComponentsPatch : BaseBytecodePatch( AccountSwitcherAccessibilityLabelFingerprint.resultOrThrow().let { result -> result.mutableMethod.apply { - val textColorIndex = getTargetIndexWithMethodReferenceNameOrThrow("setTextColor") - val setVisibilityIndex = - getTargetIndexWithMethodReferenceNameOrThrow(textColorIndex, "setVisibility") + val textColorIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setTextColor" + } + val setVisibilityIndex = indexOfFirstInstructionOrThrow(textColorIndex) { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setVisibility" + } val textViewInstruction = getInstruction(setVisibilityIndex) @@ -98,8 +111,12 @@ object AccountComponentsPatch : BaseBytecodePatch( TermsOfServiceFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = - getTargetIndexWithReferenceOrThrow("/PrivacyTosFooter;->setVisibility(I)V") + val insertIndex = indexOfFirstInstructionOrThrow { + val reference = getReference() + opcode == Opcode.INVOKE_VIRTUAL && + reference?.name == "setVisibility" && + reference.definingClass.endsWith("/PrivacyTosFooter;") + } val visibilityRegister = getInstruction(insertIndex).registerD diff --git a/src/main/kotlin/app/revanced/patches/music/actionbar/components/ActionBarComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/music/actionbar/components/ActionBarComponentsPatch.kt index 7adeadfdc..af0f94b91 100644 --- a/src/main/kotlin/app/revanced/patches/music/actionbar/components/ActionBarComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/actionbar/components/ActionBarComponentsPatch.kt @@ -15,10 +15,9 @@ import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.LikeDis import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch import app.revanced.patches.music.video.information.VideoInformationPatch -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getTargetIndexWithReferenceOrThrow -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -26,6 +25,7 @@ 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.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference import kotlin.math.min @Suppress("unused") @@ -48,7 +48,10 @@ object ActionBarComponentsPatch : BaseBytecodePatch( it.mutableMethod.apply { // hook download button - val addViewIndex = getTargetIndexWithMethodReferenceNameOrThrow("addView") + val addViewIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "addView" + } val addViewRegister = getInstruction(addViewIndex).registerD @@ -83,10 +86,15 @@ object ActionBarComponentsPatch : BaseBytecodePatch( removeInstruction(replaceIndex) // hide action button - val hasNextIndex = getTargetIndexWithMethodReferenceNameOrThrow("hasNext") + val hasNextIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_INTERFACE && + getReference()?.name == "hasNext" + } val freeRegister = min(implementation!!.registerCount - parameters.size - 2, 15) - val spannedIndex = getTargetIndexWithReferenceOrThrow(")Landroid/text/Spanned;") + val spannedIndex = indexOfFirstInstructionOrThrow { + getReference()?.returnType == "Landroid/text/Spanned;" + } val spannedRegister = getInstruction(spannedIndex).registerC val spannedReference = getInstruction(spannedIndex).reference @@ -124,7 +132,8 @@ object ActionBarComponentsPatch : BaseBytecodePatch( LikeDislikeContainerFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = getWideLiteralInstructionIndex(LikeDislikeContainer) + 2 + val insertIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(LikeDislikeContainer) + 2 val insertRegister = getInstruction(insertIndex).registerA addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/music/ads/general/AdsPatch.kt b/src/main/kotlin/app/revanced/patches/music/ads/general/AdsPatch.kt index d490534a5..9a1d8d21c 100644 --- a/src/main/kotlin/app/revanced/patches/music/ads/general/AdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/ads/general/AdsPatch.kt @@ -22,19 +22,21 @@ import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.ButtonContainer import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.FloatingLayout import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.InterstitialsContainer +import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.PrivacyTosFooter import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch import app.revanced.patches.shared.litho.LithoFilterPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithReferenceOrThrow +import app.revanced.util.getReference import app.revanced.util.getWalkerMethod -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference @Suppress("unused") object AdsPatch : BaseBytecodePatch( @@ -87,7 +89,7 @@ object AdsPatch : BaseBytecodePatch( FloatingLayoutFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val targetIndex = getWideLiteralInstructionIndex(FloatingLayout) + 2 + val targetIndex = indexOfFirstWideLiteralInstructionValueOrThrow(FloatingLayout) + 2 val targetRegister = getInstruction(targetIndex).registerA addInstruction( @@ -103,7 +105,8 @@ object AdsPatch : BaseBytecodePatch( NotifierShelfFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val linearLayoutIndex = getWideLiteralInstructionIndex(ButtonContainer) + 3 + val linearLayoutIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(ButtonContainer) + 3 val linearLayoutRegister = getInstruction(linearLayoutIndex).registerA @@ -135,16 +138,20 @@ object AdsPatch : BaseBytecodePatch( AccountMenuFooterFingerprint.resultOrThrow().let { it.mutableMethod.apply { val constIndex = - getWideLiteralInstructionIndex(SharedResourceIdPatch.PrivacyTosFooter) - val walkerIndex = getTargetIndexOrThrow(constIndex + 2, Opcode.INVOKE_VIRTUAL) - val viewIndex = getTargetIndexOrThrow(constIndex, Opcode.IGET_OBJECT) + indexOfFirstWideLiteralInstructionValueOrThrow(PrivacyTosFooter) + val walkerIndex = + indexOfFirstInstructionOrThrow(constIndex + 2, Opcode.INVOKE_VIRTUAL) + val viewIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.IGET_OBJECT) val viewReference = getInstruction(viewIndex).reference.toString() val walkerMethod = getWalkerMethod(context, walkerIndex) walkerMethod.apply { - val insertIndex = getTargetIndexWithReferenceOrThrow(viewReference) - val nullCheckIndex = getTargetIndexOrThrow(insertIndex - 1, Opcode.IF_NEZ) + val insertIndex = indexOfFirstInstructionOrThrow { + getReference()?.toString() == viewReference + } + val nullCheckIndex = + indexOfFirstInstructionOrThrow(insertIndex - 1, Opcode.IF_NEZ) val nullCheckRegister = getInstruction(nullCheckIndex).registerA diff --git a/src/main/kotlin/app/revanced/patches/music/ads/general/fingerprints/NotifierShelfFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/ads/general/fingerprints/NotifierShelfFingerprint.kt index e0ba63d86..d76a6847d 100644 --- a/src/main/kotlin/app/revanced/patches/music/ads/general/fingerprints/NotifierShelfFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/ads/general/fingerprints/NotifierShelfFingerprint.kt @@ -4,14 +4,14 @@ import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.ButtonContainer import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MusicNotifierShelf -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object NotifierShelfFingerprint : MethodFingerprint( returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(MusicNotifierShelf) - && methodDef.containsWideLiteralInstructionIndex(ButtonContainer) + methodDef.containsWideLiteralInstructionValue(MusicNotifierShelf) + && methodDef.containsWideLiteralInstructionValue(ButtonContainer) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/ads/general/fingerprints/ShowDialogCommandFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/ads/general/fingerprints/ShowDialogCommandFingerprint.kt index b83d05c76..49e108d66 100644 --- a/src/main/kotlin/app/revanced/patches/music/ads/general/fingerprints/ShowDialogCommandFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/ads/general/fingerprints/ShowDialogCommandFingerprint.kt @@ -2,7 +2,7 @@ package app.revanced.patches.music.ads.general.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.SlidingDialogAnimation -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.Opcode internal object ShowDialogCommandFingerprint : MethodFingerprint( @@ -16,7 +16,7 @@ internal object ShowDialogCommandFingerprint : MethodFingerprint( // 6.26 and earlier has a different first parameter. // Since this fingerprint is somewhat weak, work around by checking for both method parameter signatures. customFingerprint = custom@{ methodDef, _ -> - if (!methodDef.containsWideLiteralInstructionIndex(SlidingDialogAnimation)) { + if (!methodDef.containsWideLiteralInstructionValue(SlidingDialogAnimation)) { return@custom false } // 6.26 and earlier parameters are: "L", "L" diff --git a/src/main/kotlin/app/revanced/patches/music/flyoutmenu/components/FlyoutMenuComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/music/flyoutmenu/components/FlyoutMenuComponentsPatch.kt index 9bcd39621..3ec2960fa 100644 --- a/src/main/kotlin/app/revanced/patches/music/flyoutmenu/components/FlyoutMenuComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/flyoutmenu/components/FlyoutMenuComponentsPatch.kt @@ -5,7 +5,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.music.flyoutmenu.components.fingerprints.DialogSolidFingerprint import app.revanced.patches.music.flyoutmenu.components.fingerprints.EndButtonsContainerFingerprint @@ -20,17 +19,18 @@ import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH import app.revanced.patches.music.utils.integrations.Constants.FLYOUT_CLASS_DESCRIPTOR import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.EndButtonsContainer +import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.TrimSilenceSwitch import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch import app.revanced.patches.music.utils.videotype.VideoTypeHookPatch import app.revanced.patches.music.video.information.VideoInformationPatch import app.revanced.patches.shared.litho.LithoFilterPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.findMethodOrThrow +import app.revanced.util.getReference import app.revanced.util.getWalkerMethod -import app.revanced.util.getWideLiteralInstructionIndex import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -88,7 +88,7 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch( // region patch for enable trim silence TrimSilenceConfigFingerprint.result?.let { - TrimSilenceConfigFingerprint.literalInstructionBooleanHook( + TrimSilenceConfigFingerprint.injectLiteralInstructionBooleanCall( 45619123, "$FLYOUT_CLASS_DESCRIPTOR->enableTrimSilence(Z)Z" ) @@ -96,40 +96,39 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch( TrimSilenceSwitchFingerprint.resultOrThrow().let { it.mutableMethod.apply { val constIndex = - getWideLiteralInstructionIndex(SharedResourceIdPatch.TrimSilenceSwitch) + indexOfFirstWideLiteralInstructionValueOrThrow(TrimSilenceSwitch) val onCheckedChangedListenerIndex = - getTargetIndexOrThrow(constIndex, Opcode.INVOKE_DIRECT) + indexOfFirstInstructionOrThrow(constIndex, Opcode.INVOKE_DIRECT) val onCheckedChangedListenerReference = getInstruction(onCheckedChangedListenerIndex).reference val onCheckedChangedListenerDefiningClass = (onCheckedChangedListenerReference as MethodReference).definingClass - val onCheckedChangedListenerClass = - context.findClass(onCheckedChangedListenerDefiningClass)!!.mutableClass - - onCheckedChangedListenerClass.methods.find { method -> method.name == "onCheckedChanged" } - ?.apply { - val walkerIndex = indexOfFirstInstructionOrThrow { - val reference = - ((this as? ReferenceInstruction)?.reference as? MethodReference) + context.findMethodOrThrow(onCheckedChangedListenerDefiningClass) { + name == "onCheckedChanged" + }.apply { + val onCheckedChangedWalkerIndex = + indexOfFirstInstructionOrThrow { + val reference = getReference() opcode == Opcode.INVOKE_VIRTUAL && reference?.returnType == "V" && reference.parameterTypes.size == 1 && reference.parameterTypes[0] == "Z" } - getWalkerMethod(context, walkerIndex).apply { - val insertIndex = getTargetIndexOrThrow(Opcode.MOVE_RESULT) - val insertRegister = - getInstruction(insertIndex).registerA - addInstructions( - insertIndex + 1, """ + getWalkerMethod(context, onCheckedChangedWalkerIndex).apply { + val insertIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT) + val insertRegister = + getInstruction(insertIndex).registerA + + addInstructions( + insertIndex + 1, """ invoke-static {v$insertRegister}, $FLYOUT_CLASS_DESCRIPTOR->enableTrimSilenceSwitch(Z)Z move-result v$insertRegister """ - ) - } - } ?: throw PatchException("onClickClass not found!") + ) + } + } } } @@ -142,7 +141,7 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch( MenuItemFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val freeIndex = getTargetIndexOrThrow(Opcode.OR_INT_LIT16) + val freeIndex = indexOfFirstInstructionOrThrow(Opcode.OR_INT_LIT16) val textViewIndex = it.scanResult.patternScanResult!!.startIndex val imageViewIndex = it.scanResult.patternScanResult!!.endIndex @@ -175,8 +174,10 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch( TouchOutsideFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val setOnClickListenerIndex = - getTargetIndexWithMethodReferenceNameOrThrow("setOnClickListener") + val setOnClickListenerIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setOnClickListener" + } val setOnClickListenerRegister = getInstruction(setOnClickListenerIndex).registerC @@ -189,8 +190,10 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch( EndButtonsContainerFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val startIndex = getWideLiteralInstructionIndex(EndButtonsContainer) - val targetIndex = getTargetIndexOrThrow(startIndex, Opcode.MOVE_RESULT_OBJECT) + val startIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(EndButtonsContainer) + val targetIndex = + indexOfFirstInstructionOrThrow(startIndex, Opcode.MOVE_RESULT_OBJECT) val targetRegister = getInstruction(targetIndex).registerA addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/music/general/components/LayoutComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/music/general/components/LayoutComponentsPatch.kt index 0c277ef54..f43d509f2 100644 --- a/src/main/kotlin/app/revanced/patches/music/general/components/LayoutComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/general/components/LayoutComponentsPatch.kt @@ -27,15 +27,17 @@ import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKA import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch +import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MusicTasteBuilderShelf +import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.PlayerOverlayChip import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.TopBarMenuItemImageView import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch import app.revanced.patches.shared.litho.LithoFilterPatch import app.revanced.patches.shared.settingmenu.SettingsMenuPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getWideLiteralInstructionIndex -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.alsoResolve +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -99,7 +101,7 @@ object LayoutComponentsPatch : BaseBytecodePatch( PlayerOverlayChipFingerprint.resultOrThrow().let { it.mutableMethod.apply { val targetIndex = - getWideLiteralInstructionIndex(SharedResourceIdPatch.PlayerOverlayChip) + 2 + indexOfFirstWideLiteralInstructionValueOrThrow(PlayerOverlayChip) + 2 val targetRegister = getInstruction(targetIndex).registerA addInstruction( @@ -176,8 +178,10 @@ object LayoutComponentsPatch : BaseBytecodePatch( if (SettingsPatch.upward0642) { TopBarMenuItemImageViewFingerprint.resultOrThrow().mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(TopBarMenuItemImageView) - val targetIndex = getTargetIndexOrThrow(constIndex, Opcode.MOVE_RESULT_OBJECT) + val constIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(TopBarMenuItemImageView) + val targetIndex = + indexOfFirstInstructionOrThrow(constIndex, Opcode.MOVE_RESULT_OBJECT) val targetRegister = getInstruction(targetIndex).registerA addInstruction( @@ -193,7 +197,7 @@ object LayoutComponentsPatch : BaseBytecodePatch( // region patch for hide sound search button SoundSearchFingerprint.result?.let { - SoundSearchFingerprint.literalInstructionBooleanHook( + SoundSearchFingerprint.injectLiteralInstructionBooleanCall( 45625491, "$GENERAL_CLASS_DESCRIPTOR->hideSoundSearchButton(Z)Z" ) @@ -227,8 +231,9 @@ object LayoutComponentsPatch : BaseBytecodePatch( parentResult.mutableMethod.apply { val constIndex = - getWideLiteralInstructionIndex(SharedResourceIdPatch.MusicTasteBuilderShelf) - val targetIndex = getTargetIndexOrThrow(constIndex, Opcode.MOVE_RESULT_OBJECT) + indexOfFirstWideLiteralInstructionValueOrThrow(MusicTasteBuilderShelf) + val targetIndex = + indexOfFirstInstructionOrThrow(constIndex, Opcode.MOVE_RESULT_OBJECT) val targetRegister = getInstruction(targetIndex).registerA addInstruction( @@ -263,14 +268,11 @@ object LayoutComponentsPatch : BaseBytecodePatch( // region patch for hide voice search button - SearchBarFingerprint.resolve( - context, - SearchBarParentFingerprint.resultOrThrow().classDef - ) - SearchBarFingerprint.resultOrThrow().let { + SearchBarFingerprint.alsoResolve( + context, SearchBarParentFingerprint + ).let { it.mutableMethod.apply { - val setVisibilityIndex = - getTargetIndexWithMethodReferenceNameOrThrow("setVisibility") + val setVisibilityIndex = SearchBarFingerprint.indexOfVisibilityInstruction(this) val setVisibilityInstruction = getInstruction(setVisibilityIndex) diff --git a/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/HistoryMenuItemFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/HistoryMenuItemFingerprint.kt index bbf6b50ce..b4a405384 100644 --- a/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/HistoryMenuItemFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/HistoryMenuItemFingerprint.kt @@ -3,7 +3,7 @@ package app.revanced.patches.music.general.components.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.HistoryMenuItem -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode @@ -16,7 +16,7 @@ internal object HistoryMenuItemFingerprint : MethodFingerprint( Opcode.RETURN_VOID ), customFingerprint = { methodDef, classDef -> - methodDef.containsWideLiteralInstructionIndex(HistoryMenuItem) + methodDef.containsWideLiteralInstructionValue(HistoryMenuItem) && classDef.methods.count() == 5 } ) diff --git a/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/HistoryMenuItemOfflineTabFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/HistoryMenuItemOfflineTabFingerprint.kt index e875e2be9..1453be5ea 100644 --- a/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/HistoryMenuItemOfflineTabFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/HistoryMenuItemOfflineTabFingerprint.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.HistoryMenuItem import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.OfflineSettingsMenuItem -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode @@ -17,7 +17,7 @@ internal object HistoryMenuItemOfflineTabFingerprint : MethodFingerprint( Opcode.RETURN_VOID ), customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(HistoryMenuItem) - && methodDef.containsWideLiteralInstructionIndex(OfflineSettingsMenuItem) + methodDef.containsWideLiteralInstructionValue(HistoryMenuItem) + && methodDef.containsWideLiteralInstructionValue(OfflineSettingsMenuItem) } ) diff --git a/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/SearchBarFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/SearchBarFingerprint.kt index fbcd0ec91..3ba4a400b 100644 --- a/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/SearchBarFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/SearchBarFingerprint.kt @@ -1,8 +1,22 @@ package app.revanced.patches.music.general.components.fingerprints -import app.revanced.util.fingerprint.MethodReferenceNameFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.music.general.components.fingerprints.SearchBarFingerprint.indexOfVisibilityInstruction +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionReversed +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.MethodReference -object SearchBarFingerprint : MethodReferenceNameFingerprint( +object SearchBarFingerprint : MethodFingerprint( returnType = "V", - reference = { "setVisibility" } -) \ No newline at end of file + customFingerprint = { methodDef, _ -> + indexOfVisibilityInstruction(methodDef) >= 0 + } +) { + fun indexOfVisibilityInstruction(methodDef: Method) = + methodDef.indexOfFirstInstructionReversed { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setVisibility" + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/general/oldstylelibraryshelf/OldStyleLibraryShelfPatch.kt b/src/main/kotlin/app/revanced/patches/music/general/oldstylelibraryshelf/OldStyleLibraryShelfPatch.kt index de8629052..8201e0701 100644 --- a/src/main/kotlin/app/revanced/patches/music/general/oldstylelibraryshelf/OldStyleLibraryShelfPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/general/oldstylelibraryshelf/OldStyleLibraryShelfPatch.kt @@ -8,8 +8,8 @@ import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKA import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndexReversedOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -27,8 +27,9 @@ object OldStyleLibraryShelfPatch : BaseBytecodePatch( BrowseIdFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val stringIndex = getStringInstructionIndex("FEmusic_offline") - val targetIndex = getTargetIndexReversedOrThrow(stringIndex, Opcode.IGET_OBJECT) + val stringIndex = indexOfFirstStringInstructionOrThrow("FEmusic_offline") + val targetIndex = + indexOfFirstInstructionReversedOrThrow(stringIndex, Opcode.IGET_OBJECT) val targetRegister = getInstruction(targetIndex).registerA addInstructions( diff --git a/src/main/kotlin/app/revanced/patches/music/general/redirection/DislikeRedirectionPatch.kt b/src/main/kotlin/app/revanced/patches/music/general/redirection/DislikeRedirectionPatch.kt index 703c0072b..fca2cf297 100644 --- a/src/main/kotlin/app/revanced/patches/music/general/redirection/DislikeRedirectionPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/general/redirection/DislikeRedirectionPatch.kt @@ -11,11 +11,11 @@ import app.revanced.patches.music.utils.fingerprints.PendingIntentReceiverFinger import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.getTargetIndexWithReferenceOrThrow +import app.revanced.util.getReference import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -41,13 +41,14 @@ object DislikeRedirectionPatch : BaseBytecodePatch( PendingIntentReceiverFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val startIndex = getStringInstructionIndex("YTM Dislike") + val startIndex = indexOfFirstStringInstructionOrThrow("YTM Dislike") val onClickRelayIndex = - getTargetIndexReversedOrThrow(startIndex, Opcode.INVOKE_VIRTUAL) + indexOfFirstInstructionReversedOrThrow(startIndex, Opcode.INVOKE_VIRTUAL) val onClickRelayMethod = getWalkerMethod(context, onClickRelayIndex) onClickRelayMethod.apply { - val onClickMethodIndex = getTargetIndexReversedOrThrow(Opcode.INVOKE_DIRECT) + val onClickMethodIndex = + indexOfFirstInstructionReversedOrThrow(Opcode.INVOKE_DIRECT) val onClickMethod = getWalkerMethod(context, onClickMethodIndex) onClickMethod.apply { @@ -70,7 +71,9 @@ object DislikeRedirectionPatch : BaseBytecodePatch( DislikeButtonOnClickListenerFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val onClickIndex = getTargetIndexWithReferenceOrThrow(onClickReference.toString()) + val onClickIndex = indexOfFirstInstructionOrThrow { + getReference()?.toString() == onClickReference.toString() + } injectCall(onClickIndex) } } @@ -84,7 +87,7 @@ object DislikeRedirectionPatch : BaseBytecodePatch( } private fun MutableMethod.injectCall(onClickIndex: Int) { - val targetIndex = getTargetIndexReversedOrThrow(onClickIndex, Opcode.IF_EQZ) + val targetIndex = indexOfFirstInstructionReversedOrThrow(onClickIndex, Opcode.IF_EQZ) val insertRegister = getInstruction(targetIndex).registerA addInstructionsWithLabels( diff --git a/src/main/kotlin/app/revanced/patches/music/general/redirection/fingerprints/DislikeButtonOnClickListenerFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/general/redirection/fingerprints/DislikeButtonOnClickListenerFingerprint.kt index a405b7204..95a496b57 100644 --- a/src/main/kotlin/app/revanced/patches/music/general/redirection/fingerprints/DislikeButtonOnClickListenerFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/general/redirection/fingerprints/DislikeButtonOnClickListenerFingerprint.kt @@ -2,7 +2,7 @@ package app.revanced.patches.music.general.redirection.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object DislikeButtonOnClickListenerFingerprint : MethodFingerprint( @@ -10,7 +10,7 @@ internal object DislikeButtonOnClickListenerFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = listOf("Landroid/view/View;"), customFingerprint = handler@{ methodDef, _ -> - if (!methodDef.containsWideLiteralInstructionIndex(53465)) + if (!methodDef.containsWideLiteralInstructionValue(53465)) return@handler false methodDef.name == "onClick" diff --git a/src/main/kotlin/app/revanced/patches/music/layout/branding/icon/CustomBrandingIconPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/branding/icon/CustomBrandingIconPatch.kt index cff91ffde..1a4c02fa8 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/branding/icon/CustomBrandingIconPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/branding/icon/CustomBrandingIconPatch.kt @@ -31,6 +31,9 @@ object CustomBrandingIconPatch : BaseResourcePatch( "MMT" to "mmt", "MMT Blue" to "mmt_blue", "MMT Green" to "mmt_green", + "MMT Orange" to "mmt_orange", + "MMT Pink" to "mmt_pink", + "MMT Turquoise" to "mmt_turquoise", "MMT Yellow" to "mmt_yellow", "Revancify Blue" to "revancify_blue", "Revancify Red" to "revancify_red", diff --git a/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/BackgroundPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/BackgroundPlaybackPatch.kt index 8e95694bf..ed4e79c7f 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/BackgroundPlaybackPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/BackgroundPlaybackPatch.kt @@ -10,15 +10,16 @@ import app.revanced.patches.music.misc.backgroundplayback.fingerprints.KidsBackg import app.revanced.patches.music.misc.backgroundplayback.fingerprints.MusicBrowserServiceFingerprint import app.revanced.patches.music.misc.backgroundplayback.fingerprints.PodCastConfigFingerprint import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE -import app.revanced.util.getStartsWithStringInstructionIndex -import app.revanced.util.getStringInstructionIndex +import app.revanced.util.getReference import app.revanced.util.getWalkerMethod +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode 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.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Suppress("unused") object BackgroundPlaybackPatch : BaseBytecodePatch( @@ -51,26 +52,20 @@ object BackgroundPlaybackPatch : BaseBytecodePatch( // don't play music video MusicBrowserServiceFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val targetIndex = - getStartsWithStringInstructionIndex("MBS: Return empty root for client: %s") - - for (index in targetIndex downTo 0) { - if (getInstruction(index).opcode != Opcode.INVOKE_VIRTUAL) continue - - val targetReference = getInstruction(index).reference - - if (!targetReference.toString().endsWith("()Z")) continue - - val walkerMethod = getWalkerMethod(context, index) - - walkerMethod.addInstructions( - 0, """ - const/4 v0, 0x1 - return v0 - """ - ) - break + val stringIndex = MusicBrowserServiceFingerprint.indexOfMBSInstruction(this) + val targetIndex = indexOfFirstInstructionReversedOrThrow(stringIndex) { + val reference = getReference() + opcode == Opcode.INVOKE_VIRTUAL && + reference?.returnType == "Z" && + reference.parameterTypes.size == 0 } + + getWalkerMethod(context, targetIndex).addInstructions( + 0, """ + const/4 v0, 0x1 + return v0 + """ + ) } } @@ -97,7 +92,8 @@ object BackgroundPlaybackPatch : BaseBytecodePatch( } dataSavingSettingsFragmentFingerprintResult!!.mutableMethod.apply { - val insertIndex = getStringInstructionIndex("pref_key_dont_play_nma_video") + 4 + val insertIndex = + indexOfFirstStringInstructionOrThrow("pref_key_dont_play_nma_video") + 4 val targetRegister = getInstruction(insertIndex).registerD addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/fingerprints/MusicBrowserServiceFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/fingerprints/MusicBrowserServiceFingerprint.kt index df191491c..2823a0079 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/fingerprints/MusicBrowserServiceFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/fingerprints/MusicBrowserServiceFingerprint.kt @@ -2,8 +2,13 @@ package app.revanced.patches.music.misc.backgroundplayback.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.getStartsWithStringInstructionIndex +import app.revanced.patches.music.misc.backgroundplayback.fingerprints.MusicBrowserServiceFingerprint.indexOfMBSInstruction +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.StringReference internal object MusicBrowserServiceFingerprint : MethodFingerprint( returnType = "L", @@ -13,6 +18,12 @@ internal object MusicBrowserServiceFingerprint : MethodFingerprint( if (!methodDef.definingClass.endsWith("/MusicBrowserService;")) return@custom false - methodDef.getStartsWithStringInstructionIndex("MBS: Return empty root for client: %s") > 0 + indexOfMBSInstruction(methodDef) >= 0 } -) \ No newline at end of file +) { + fun indexOfMBSInstruction(methodDef: Method) = + methodDef.indexOfFirstInstruction { + opcode == Opcode.CONST_STRING && + getReference()?.string?.startsWith("MBS: Return empty root for client: %s") == true + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/misc/share/ShareSheetPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/share/ShareSheetPatch.kt index 204d168a0..8a3b9b0a5 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/share/ShareSheetPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/share/ShareSheetPatch.kt @@ -12,8 +12,8 @@ import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.BottomS import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch import app.revanced.patches.shared.litho.LithoFilterPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -40,8 +40,8 @@ object ShareSheetPatch : BaseBytecodePatch( override fun execute(context: BytecodeContext) { BottomSheetRecyclerViewFingerprint.resultOrThrow().mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(BottomSheetRecyclerView) - val targetIndex = getTargetIndexOrThrow(constIndex, Opcode.CHECK_CAST) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(BottomSheetRecyclerView) + val targetIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.CHECK_CAST) val targetRegister = getInstruction(targetIndex).registerA addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/music/misc/splash/CairoSplashAnimationPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/splash/CairoSplashAnimationPatch.kt index ae0465ae4..5b345a176 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/splash/CairoSplashAnimationPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/splash/CairoSplashAnimationPatch.kt @@ -1,25 +1,41 @@ package app.revanced.patches.music.misc.splash import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.music.misc.splash.fingerprints.CairoSplashAnimationConfigFingerprint import app.revanced.patches.music.utils.integrations.Constants.MISC_PATH +import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch +import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MainActivityLaunchAnimation import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall +import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Patch( name = "Disable Cairo splash animation", description = "Adds an option to disable Cairo splash animation.", - dependencies = [SettingsPatch::class], + dependencies = [ + SettingsPatch::class, + SharedResourceIdPatch::class + ], compatiblePackages = [ CompatiblePackage( "com.google.android.apps.youtube.music", [ "7.06.54", - "7.16.52", + "7.16.53", ] ) ] @@ -28,22 +44,57 @@ import app.revanced.util.literalInstructionBooleanHook object CairoSplashAnimationPatch : BytecodePatch( setOf(CairoSplashAnimationConfigFingerprint) ) { + private const val INTEGRATIONS_METHOD_DESCRIPTOR = + "$MISC_PATH/CairoSplashAnimationPatch;->disableCairoSplashAnimation(Z)Z" + override fun execute(context: BytecodeContext) { - CairoSplashAnimationConfigFingerprint.result?.let { - CairoSplashAnimationConfigFingerprint.literalInstructionBooleanHook( + if (!SettingsPatch.upward0706) { + println("WARNING: This patch is not supported in this version. Use YouTube Music 7.06.54 or later.") + return + } else if (!SettingsPatch.upward0720) { + CairoSplashAnimationConfigFingerprint.injectLiteralInstructionBooleanCall( 45635386, - "$MISC_PATH/CairoSplashAnimationPatch;->disableCairoSplashAnimation(Z)Z" - ) - - SettingsPatch.addSwitchPreference( - CategoryType.MISC, - "revanced_disable_cairo_splash_animation", - "false" + INTEGRATIONS_METHOD_DESCRIPTOR ) + } else { + CairoSplashAnimationConfigFingerprint.resultOrThrow().mutableMethod.apply { + val literalIndex = indexOfFirstWideLiteralInstructionValueOrThrow( + MainActivityLaunchAnimation + ) + val insertIndex = indexOfFirstInstructionReversedOrThrow(literalIndex) { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setContentView" + } + 1 + val viewStubFindViewByIdIndex = indexOfFirstInstructionOrThrow(literalIndex) { + val reference = getReference() + opcode == Opcode.INVOKE_VIRTUAL && + reference?.name == "findViewById" && + reference.definingClass != "Landroid/view/View;" + } + val freeRegister = + getInstruction(viewStubFindViewByIdIndex).registerD + val jumpIndex = indexOfFirstInstructionReversedOrThrow( + viewStubFindViewByIdIndex, + Opcode.IGET_OBJECT + ) + addInstructionsWithLabels( + insertIndex, """ + const/4 v$freeRegister, 0x1 + invoke-static {v$freeRegister}, $INTEGRATIONS_METHOD_DESCRIPTOR + move-result v$freeRegister + if-eqz v$freeRegister, :skip + """, ExternalLabel("skip", getInstruction(jumpIndex)) + ) + } } - ?: println("WARNING: This patch is not supported in this version. Use YouTube Music 7.06.54 or later.") + + SettingsPatch.addSwitchPreference( + CategoryType.MISC, + "revanced_disable_cairo_splash_animation", + "false" + ) } } diff --git a/src/main/kotlin/app/revanced/patches/music/misc/splash/fingerprints/CairoSplashAnimationConfigFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/splash/fingerprints/CairoSplashAnimationConfigFingerprint.kt index 54bf6c3e7..1050b4f56 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/splash/fingerprints/CairoSplashAnimationConfigFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/splash/fingerprints/CairoSplashAnimationConfigFingerprint.kt @@ -1,10 +1,25 @@ package app.revanced.patches.music.misc.splash.fingerprints -import app.revanced.util.fingerprint.LiteralValueFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MainActivityLaunchAnimation +import app.revanced.patches.music.utils.settings.SettingsPatch +import app.revanced.util.indexOfFirstWideLiteralInstructionValue /** * This fingerprint is compatible with YouTube Music v7.06.53+ */ -internal object CairoSplashAnimationConfigFingerprint : LiteralValueFingerprint( - literalSupplier = { 45635386 } +internal object CairoSplashAnimationConfigFingerprint : MethodFingerprint( + returnType = "V", + customFingerprint = handler@{ methodDef, _ -> + if (methodDef.definingClass != "Lcom/google/android/apps/youtube/music/activities/MusicActivity;") + return@handler false + if (methodDef.name != "onCreate") + return@handler false + + if (SettingsPatch.upward0720) { + methodDef.indexOfFirstWideLiteralInstructionValue(MainActivityLaunchAnimation) >= 0 + } else { + methodDef.indexOfFirstWideLiteralInstructionValue(45635386) >= 0 + } + } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/navigation/components/NavigationBarComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/music/navigation/components/NavigationBarComponentsPatch.kt index adcd24adf..a2e16a724 100644 --- a/src/main/kotlin/app/revanced/patches/music/navigation/components/NavigationBarComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/navigation/components/NavigationBarComponentsPatch.kt @@ -11,13 +11,12 @@ import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKA import app.revanced.patches.music.utils.integrations.Constants.NAVIGATION_CLASS_DESCRIPTOR import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.ColorGrey +import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.Text1 import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch import app.revanced.util.getReference -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getWideLiteralInstructionIndex import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -50,7 +49,7 @@ object NavigationBarComponentsPatch : BaseBytecodePatch( * Enable black navigation bar */ TabLayoutFingerprint.resultOrThrow().mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(ColorGrey) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(ColorGrey) val insertIndex = indexOfFirstInstructionOrThrow(constIndex) { opcode == Opcode.INVOKE_VIRTUAL && getReference()?.name == "setBackgroundColor" @@ -70,8 +69,9 @@ object NavigationBarComponentsPatch : BaseBytecodePatch( */ TabLayoutTextFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(SharedResourceIdPatch.Text1) - val targetIndex = getTargetIndexOrThrow(constIndex, Opcode.CHECK_CAST) + val constIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(Text1) + val targetIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.CHECK_CAST) val targetParameter = getInstruction(targetIndex).reference val targetRegister = getInstruction(targetIndex).registerA @@ -105,9 +105,12 @@ object NavigationBarComponentsPatch : BaseBytecodePatch( it.mutableMethod.apply { val enumIndex = it.scanResult.patternScanResult!!.startIndex + 3 val enumRegister = getInstruction(enumIndex).registerA - val insertEnumIndex = getTargetIndexOrThrow(Opcode.AND_INT_LIT8) - 2 + val insertEnumIndex = indexOfFirstInstructionOrThrow(Opcode.AND_INT_LIT8) - 2 - val pivotTabIndex = getTargetIndexWithMethodReferenceNameOrThrow("getVisibility") + val pivotTabIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "getVisibility" + } val pivotTabRegister = getInstruction(pivotTabIndex).registerC addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/PlayerComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/music/player/components/PlayerComponentsPatch.kt index 8bc50eed1..cecb66c69 100644 --- a/src/main/kotlin/app/revanced/patches/music/player/components/PlayerComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/player/components/PlayerComponentsPatch.kt @@ -13,6 +13,8 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.music.player.components.fingerprints.AudioVideoSwitchToggleFingerprint +import app.revanced.patches.music.player.components.fingerprints.EngagementPanelHeightFingerprint +import app.revanced.patches.music.player.components.fingerprints.EngagementPanelHeightParentFingerprint import app.revanced.patches.music.player.components.fingerprints.HandleSearchRenderedFingerprint import app.revanced.patches.music.player.components.fingerprints.HandleSignInEventFingerprint import app.revanced.patches.music.player.components.fingerprints.InteractionLoggingEnumFingerprint @@ -33,15 +35,14 @@ import app.revanced.patches.music.player.components.fingerprints.PlayerViewPager import app.revanced.patches.music.player.components.fingerprints.QuickSeekOverlayFingerprint import app.revanced.patches.music.player.components.fingerprints.RemixGenericButtonFingerprint import app.revanced.patches.music.player.components.fingerprints.RepeatTrackFingerprint -import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint -import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint.indexOfImageViewInstruction -import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint.indexOfOrdinalInstruction +import app.revanced.patches.music.player.components.fingerprints.ShuffleOnClickFingerprint import app.revanced.patches.music.player.components.fingerprints.SwipeToCloseFingerprint import app.revanced.patches.music.player.components.fingerprints.SwitchToggleColorFingerprint import app.revanced.patches.music.player.components.fingerprints.ZenModeFingerprint import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.music.utils.fingerprints.PendingIntentReceiverFingerprint import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH +import app.revanced.patches.music.utils.integrations.Constants.INTEGRATIONS_PATH import app.revanced.patches.music.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR import app.revanced.patches.music.utils.mainactivity.MainActivityResolvePatch import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch @@ -59,24 +60,23 @@ import app.revanced.patches.music.utils.settings.SettingsPatch import app.revanced.patches.music.utils.videotype.VideoTypeHookPatch import app.revanced.patches.shared.litho.LithoFilterPatch import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT +import app.revanced.util.addStaticFieldToIntegration +import app.revanced.util.alsoResolve +import app.revanced.util.findMethodOrThrow import app.revanced.util.getReference -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndex -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.getTargetIndexWithFieldReferenceTypeOrThrow import app.revanced.util.getWalkerMethod -import app.revanced.util.getWideLiteralInstructionIndex import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.literalInstructionBooleanHook -import app.revanced.util.literalInstructionViewHook +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall +import app.revanced.util.injectLiteralInstructionViewCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow -import app.revanced.util.transformFields +import app.revanced.util.transformMethods import app.revanced.util.traverseClassHierarchy import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation import com.android.tools.smali.dexlib2.iface.MethodParameter import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @@ -87,7 +87,6 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.Reference import com.android.tools.smali.dexlib2.immutable.ImmutableField import com.android.tools.smali.dexlib2.immutable.ImmutableMethod -import com.android.tools.smali.dexlib2.util.MethodUtil import kotlin.properties.Delegates @Suppress("unused", "LocalVariableName") @@ -100,11 +99,12 @@ object PlayerComponentsPatch : BaseBytecodePatch( PlayerComponentsResourcePatch::class, SettingsPatch::class, SharedResourceIdPatch::class, - VideoTypeHookPatch::class + VideoTypeHookPatch::class, ), compatiblePackages = COMPATIBLE_PACKAGE, fingerprints = setOf( AudioVideoSwitchToggleFingerprint, + EngagementPanelHeightParentFingerprint, HandleSearchRenderedFingerprint, InteractionLoggingEnumFingerprint, MinimizedPlayerFingerprint, @@ -124,13 +124,16 @@ object PlayerComponentsPatch : BaseBytecodePatch( QuickSeekOverlayFingerprint, RemixGenericButtonFingerprint, RepeatTrackFingerprint, - ShuffleClassReferenceFingerprint, + ShuffleOnClickFingerprint, SwipeToCloseFingerprint, ) ) { private const val FILTER_CLASS_DESCRIPTOR = "$COMPONENTS_PATH/PlayerComponentsFilter;" + private const val INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR = + "$INTEGRATIONS_PATH/utils/VideoUtils;" + override fun execute(context: BytecodeContext) { // region patch for disable gesture in player @@ -145,8 +148,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( PlayerViewPager to "disablePlayerGesture" ).forEach { (literal, methodName) -> val viewPagerReference = playerViewPagerConstructorMethod.let { - val constIndex = it.getWideLiteralInstructionIndex(literal) - val targetIndex = it.getTargetIndexOrThrow(constIndex, Opcode.IPUT_OBJECT) + val constIndex = it.indexOfFirstWideLiteralInstructionValueOrThrow(literal) + val targetIndex = it.indexOfFirstInstructionOrThrow(constIndex, Opcode.IPUT_OBJECT) it.getInstruction(targetIndex).reference.toString() } @@ -156,7 +159,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( && getReference()?.toString() == viewPagerReference } val insertRegister = getInstruction(insertIndex).registerA - val jumpIndex = getTargetIndex(insertIndex, Opcode.INVOKE_VIRTUAL) + 1 + val jumpIndex = + indexOfFirstInstructionOrThrow(insertIndex, Opcode.INVOKE_VIRTUAL) + 1 addInstructionsWithLabels( insertIndex, """ @@ -198,8 +202,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( val relativeIndex = it.scanResult.patternScanResult!!.endIndex + 1 val invokeVirtualIndex = - getTargetIndexOrThrow(relativeIndex, Opcode.INVOKE_VIRTUAL) - val iGetIndex = getTargetIndexOrThrow(relativeIndex, Opcode.IGET) + indexOfFirstInstructionOrThrow(relativeIndex, Opcode.INVOKE_VIRTUAL) + val iGetIndex = indexOfFirstInstructionOrThrow(relativeIndex, Opcode.IGET) colorMathPlayerInvokeVirtualReference = getInstruction(invokeVirtualIndex).reference @@ -207,11 +211,11 @@ object PlayerComponentsPatch : BaseBytecodePatch( getInstruction(iGetIndex).reference // black player background - val invokeDirectIndex = getTargetIndexOrThrow(Opcode.INVOKE_DIRECT) + val invokeDirectIndex = indexOfFirstInstructionOrThrow(Opcode.INVOKE_DIRECT) val targetMethod = getWalkerMethod(context, invokeDirectIndex) targetMethod.apply { - val insertIndex = getTargetIndexOrThrow(0, Opcode.IF_NE) + val insertIndex = indexOfFirstInstructionOrThrow(Opcode.IF_NE) addInstructions( insertIndex, """ @@ -225,8 +229,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( } parentResult.mutableMethod.apply { - val colorGreyIndex = getWideLiteralInstructionIndex(ColorGrey) - val iPutIndex = getTargetIndexOrThrow(colorGreyIndex, Opcode.IPUT) + val colorGreyIndex = indexOfFirstWideLiteralInstructionValueOrThrow(ColorGrey) + val iPutIndex = indexOfFirstInstructionOrThrow(colorGreyIndex, Opcode.IPUT) colorMathPlayerIPutReference = getInstruction(iPutIndex).reference @@ -240,7 +244,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( mutableMethod.apply { val freeRegister = implementation!!.registerCount - parameters.size - 3 - val invokeDirectIndex = getTargetIndexReversedOrThrow(Opcode.INVOKE_DIRECT) + val invokeDirectIndex = + indexOfFirstInstructionReversedOrThrow(Opcode.INVOKE_DIRECT) val invokeDirectReference = getInstruction(invokeDirectIndex).reference @@ -401,9 +406,9 @@ object PlayerComponentsPatch : BaseBytecodePatch( reversed: Boolean ): Reference { val targetIndex = if (reversed) - getTargetIndexReversedOrThrow(swipeToDismissWidgetIndex, opcode) + indexOfFirstInstructionReversedOrThrow(swipeToDismissWidgetIndex, opcode) else - getTargetIndexOrThrow(swipeToDismissWidgetIndex, opcode) + indexOfFirstInstructionOrThrow(swipeToDismissWidgetIndex, opcode) return getInstruction(targetIndex).reference } @@ -411,7 +416,7 @@ object PlayerComponentsPatch : BaseBytecodePatch( if (!SettingsPatch.upward0642) { SwipeToCloseFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = implementation!!.instructions.size - 1 + val insertIndex = implementation!!.instructions.lastIndex val targetRegister = getInstruction(insertIndex).registerA @@ -430,8 +435,9 @@ object PlayerComponentsPatch : BaseBytecodePatch( InteractionLoggingEnumFingerprint.resultOrThrow().let { it.mutableMethod.apply { val stringIndex = - getStringInstructionIndex("INTERACTION_LOGGING_GESTURE_TYPE_SWIPE") - val sPutObjectIndex = getTargetIndexOrThrow(stringIndex, Opcode.SPUT_OBJECT) + indexOfFirstStringInstructionOrThrow("INTERACTION_LOGGING_GESTURE_TYPE_SWIPE") + val sPutObjectIndex = + indexOfFirstInstructionOrThrow(stringIndex, Opcode.SPUT_OBJECT) swipeToDismissSGetObjectReference = getInstruction(sPutObjectIndex).reference @@ -440,7 +446,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( MusicActivityWidgetFingerprint.resultOrThrow().let { it.mutableMethod.apply { - swipeToDismissWidgetIndex = getWideLiteralInstructionIndex(79500) + swipeToDismissWidgetIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(79500) swipeToDismissIGetObjectReference = getSwipeToDismissReference(Opcode.IGET_OBJECT, true) @@ -468,8 +475,9 @@ object PlayerComponentsPatch : BaseBytecodePatch( it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex) dismissBehaviorMethod.apply { - val insertIndex = - getTargetIndexWithFieldReferenceTypeOrThrow("Ljava/util/concurrent/atomic/AtomicBoolean;") + val insertIndex = indexOfFirstInstructionOrThrow { + getReference()?.type == "Ljava/util/concurrent/atomic/AtomicBoolean;" + } val primaryRegister = getInstruction(insertIndex).registerB val secondaryRegister = primaryRegister + 1 @@ -528,15 +536,12 @@ object PlayerComponentsPatch : BaseBytecodePatch( it.mutableClass.methods.find { method -> method.parameters == listOf("Landroid/view/View;", "I") }?.apply { - val bottomSheetBehaviorIndex = - implementation!!.instructions.indexOfFirst { instruction -> - instruction.opcode == Opcode.INVOKE_VIRTUAL - && instruction.getReference()?.definingClass == "Lcom/google/android/material/bottomsheet/BottomSheetBehavior;" - && instruction.getReference()?.parameterTypes?.first() == "Z" - } - if (bottomSheetBehaviorIndex < 0) - throw PatchException("Could not find bottomSheetBehaviorIndex") - + val bottomSheetBehaviorIndex = indexOfFirstInstructionOrThrow { + val reference = getReference() + opcode == Opcode.INVOKE_VIRTUAL + && reference?.definingClass == "Lcom/google/android/material/bottomsheet/BottomSheetBehavior;" + && reference.parameterTypes.first() == "Z" + } val freeRegister = getInstruction(bottomSheetBehaviorIndex).registerD @@ -592,7 +597,7 @@ object PlayerComponentsPatch : BaseBytecodePatch( SwitchToggleColorFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val invokeDirectIndex = getTargetIndexOrThrow(Opcode.INVOKE_DIRECT) + val invokeDirectIndex = indexOfFirstInstructionOrThrow(Opcode.INVOKE_DIRECT) val walkerMethod = getWalkerMethod(context, invokeDirectIndex) walkerMethod.addInstructions( @@ -624,8 +629,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( // region patch for hide audio video switch toggle AudioVideoSwitchToggleFingerprint.resultOrThrow().mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(AudioVideoSwitchToggle) - val viewIndex = getTargetIndexOrThrow(constIndex, Opcode.MOVE_RESULT_OBJECT) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(AudioVideoSwitchToggle) + val viewIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.MOVE_RESULT_OBJECT) val viewRegister = getInstruction(viewIndex).registerA addInstruction( @@ -667,7 +672,7 @@ object PlayerComponentsPatch : BaseBytecodePatch( DarkBackground, TapBloomView ).forEach { literal -> - QuickSeekOverlayFingerprint.literalInstructionViewHook( + QuickSeekOverlayFingerprint.injectLiteralInstructionViewCall( literal, smaliInstruction ) @@ -731,152 +736,85 @@ object PlayerComponentsPatch : BaseBytecodePatch( // region patch for remember shuffle state - val MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR = - "Lcom/google/android/apps/youtube/music/watchpage/MusicPlaybackControls;" + ShuffleOnClickFingerprint.resultOrThrow().mutableMethod.apply { + val accessibilityIndex = + ShuffleOnClickFingerprint.indexOfAccessibilityInstruction(this) - lateinit var rememberShuffleStateObjectClass: String - lateinit var rememberShuffleStateImageViewReference: Reference - lateinit var rememberShuffleStateShuffleStateLabel: String + // region set shuffle enum - ShuffleClassReferenceFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - rememberShuffleStateObjectClass = definingClass - - val constIndex = getWideLiteralInstructionIndex(45468) - val iGetObjectIndex = getTargetIndexOrThrow(constIndex, Opcode.IGET_OBJECT) - val checkCastIndex = getTargetIndexOrThrow(iGetObjectIndex, Opcode.CHECK_CAST) - - val ordinalIndex = indexOfOrdinalInstruction(this) - val imageViewIndex = indexOfImageViewInstruction(this) - - val iGetObjectReference = - getInstruction(iGetObjectIndex).reference - val invokeInterfaceReference = - getInstruction(iGetObjectIndex + 1).reference - val checkCastReference = - getInstruction(checkCastIndex).reference - val getOrdinalClassReference = - getInstruction(checkCastIndex + 1).reference - val ordinalReference = - getInstruction(ordinalIndex).reference - - rememberShuffleStateImageViewReference = - getInstruction(imageViewIndex).reference - - rememberShuffleStateShuffleStateLabel = """ - iget-object v1, v0, $iGetObjectReference - invoke-interface {v1}, $invokeInterfaceReference - move-result-object v1 - check-cast v1, $checkCastReference - """ - - rememberShuffleStateShuffleStateLabel += if (getInstruction(checkCastIndex + 1).opcode == Opcode.INVOKE_VIRTUAL) { - // YouTube Music 7.16.52+ - """ - invoke-virtual {v1}, $getOrdinalClassReference - move-result-object v1 - - """.trimIndent() - } else { - """ - iget-object v1, v1, $getOrdinalClassReference - - """.trimIndent() - } - - rememberShuffleStateShuffleStateLabel += """ - invoke-virtual {v1}, $ordinalReference - move-result v1 - - """.trimIndent() + val enumIndex = indexOfFirstInstructionReversedOrThrow(accessibilityIndex) { + opcode == Opcode.INVOKE_DIRECT && + getReference()?.returnType == "Ljava/lang/String;" } + val enumRegister = getInstruction(enumIndex).registerD + val enumClass = (getInstruction(enumIndex).reference as MethodReference).parameterTypes.first() - val constructorMethod = - it.mutableClass.methods.first { method -> MethodUtil.isConstructor(method) } - val onClickMethod = it.mutableClass.methods.first { method -> method.name == "onClick" } + addInstruction( + enumIndex, + "invoke-static {v$enumRegister}, $PLAYER_CLASS_DESCRIPTOR->setShuffleState(Ljava/lang/Enum;)V" + ) - constructorMethod.apply { - addInstruction( - implementation!!.instructions.lastIndex, - "sput-object p0, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->shuffleClass:$rememberShuffleStateObjectClass" - ) - } + // endregion - onClickMethod.apply { - addInstructions( - 0, """ - move-object v0, p0 - """ + rememberShuffleStateShuffleStateLabel + """ - invoke-static {v1}, $PLAYER_CLASS_DESCRIPTOR->setShuffleState(I)V - """ - ) - } + // region set static field + + val shuffleClassIndex = indexOfFirstInstructionReversedOrThrow(accessibilityIndex, Opcode.CHECK_CAST) + val shuffleClass = getInstruction(shuffleClassIndex).reference.toString() + val shuffleMutableClass = context.findClass { classDef -> + classDef.type == shuffleClass + }!!.mutableClass + + val shuffleMethod = shuffleMutableClass.methods.find { method -> + method.parameterTypes.firstOrNull() == enumClass && + method.parameterTypes.size == 1 && + method.returnType == "V" + } ?: throw PatchException("target not found") + + val smaliInstructions = + """ + if-eqz v0, :ignore + sget-object v1, $enumClass->b:$enumClass + invoke-virtual {v0, v1}, $shuffleClass->${shuffleMethod.name}($enumClass)V + :ignore + return-void + """ + + context.addStaticFieldToIntegration( + INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR, + "shuffleTracks", + "shuffleClass", + shuffleClass, + smaliInstructions + ) + + // endregion - context.traverseClassHierarchy(it.mutableClass) { - accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL - transformFields { - ImmutableField( + // region make all methods accessible + + context.traverseClassHierarchy(shuffleMutableClass) { + transformMethods { + ImmutableMethod( definingClass, name, - type, - AccessFlags.PUBLIC or AccessFlags.PUBLIC, - null, + parameters, + returnType, + AccessFlags.PUBLIC or AccessFlags.FINAL, annotations, - null + hiddenApiRestrictions, + implementation ).toMutable() } } - } - - MusicPlaybackControlsFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - addInstruction( - 0, - "invoke-virtual {v0}, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->rememberShuffleState()V" - ) - val shuffleField = ImmutableField( - definingClass, - "shuffleClass", - rememberShuffleStateObjectClass, - AccessFlags.PUBLIC or AccessFlags.STATIC, - null, - annotations, - null - ).toMutable() - - val shuffleMethod = ImmutableMethod( - definingClass, - "rememberShuffleState", - emptyList(), - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - annotations, null, - MutableMethodImplementation(5) - ).toMutable() - - shuffleMethod.addInstructionsWithLabels( - 0, """ - invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->getShuffleState()I - move-result v2 - if-nez v2, :dont_shuffle - sget-object v0, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->shuffleClass:$rememberShuffleStateObjectClass - """ + rememberShuffleStateShuffleStateLabel + """ - iget-object v3, v0, $rememberShuffleStateImageViewReference - if-eqz v3, :dont_shuffle - invoke-virtual {v3}, Landroid/view/View;->callOnClick()Z - if-eqz v1, :dont_shuffle - invoke-virtual {v3}, Landroid/view/View;->callOnClick()Z - :dont_shuffle - return-void - """ - ) + // endregion - it.mutableClass.methods.add(shuffleMethod) - it.mutableClass.staticFields.add(shuffleField) - } } + MusicPlaybackControlsFingerprint.resultOrThrow().mutableMethod.addInstruction( + 0, + "invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->shuffleTracks()V" + ) + SettingsPatch.addSwitchPreference( CategoryType.PLAYER, "revanced_remember_shuffle_state", @@ -887,12 +825,84 @@ object PlayerComponentsPatch : BaseBytecodePatch( // region patch for restore old comments popup panels - OldEngagementPanelFingerprint.result?.let { - OldEngagementPanelFingerprint.literalInstructionBooleanHook( + var restoreOldCommentsPopupPanel = false + + if (SettingsPatch.upward0627 && !SettingsPatch.upward0718) { + OldEngagementPanelFingerprint.injectLiteralInstructionBooleanCall( 45427672, "$PLAYER_CLASS_DESCRIPTOR->restoreOldCommentsPopUpPanels(Z)Z" ) + restoreOldCommentsPopupPanel = true + } else if (SettingsPatch.upward0718) { + + // region disable player from being pushed to the top when opening a comment + + MppWatchWhileLayoutFingerprint.resultOrThrow().mutableMethod.apply { + val callableIndex = + MppWatchWhileLayoutFingerprint.indexOfCallableInstruction(this) + val insertIndex = + indexOfFirstInstructionReversedOrThrow(callableIndex, Opcode.NEW_INSTANCE) + val insertRegister = getInstruction(insertIndex).registerA + + addInstructionsWithLabels( + insertIndex, """ + invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->restoreOldCommentsPopUpPanels()Z + move-result v$insertRegister + if-eqz v$insertRegister, :restore + """, ExternalLabel("restore", getInstruction(callableIndex + 1)) + ) + } + + // endregion + + // region region limit the height of the engagement panel + + EngagementPanelHeightFingerprint.alsoResolve( + context, EngagementPanelHeightParentFingerprint + ).let { + it.mutableMethod.apply { + val targetIndex = it.scanResult.patternScanResult!!.endIndex + val targetRegister = + getInstruction(targetIndex).registerA + + addInstructions( + targetIndex + 1, """ + invoke-static {v$targetRegister}, $PLAYER_CLASS_DESCRIPTOR->restoreOldCommentsPopUpPanels(Z)Z + move-result v$targetRegister + """ + ) + } + } + + MiniPlayerDefaultViewVisibilityFingerprint.resultOrThrow().let { + it.mutableClass.methods.find { method -> + method.parameters == listOf("Landroid/view/View;", "I") + }?.apply { + val targetIndex = indexOfFirstInstructionOrThrow { + val reference = getReference() + opcode == Opcode.INVOKE_INTERFACE + && reference?.returnType == "Z" + && reference.parameterTypes.size == 0 + } + 1 + val targetRegister = + getInstruction(targetIndex).registerA + + addInstructions( + targetIndex + 1, """ + invoke-static {v$targetRegister}, $PLAYER_CLASS_DESCRIPTOR->restoreOldCommentsPopUpPanels(Z)Z + move-result v$targetRegister + """ + ) + } ?: throw PatchException("Could not find targetMethod") + + } + + // endregion + restoreOldCommentsPopupPanel = true + } + + if (restoreOldCommentsPopupPanel) { SettingsPatch.addSwitchPreference( CategoryType.PLAYER, "revanced_restore_old_comments_popup_panels", @@ -905,7 +915,7 @@ object PlayerComponentsPatch : BaseBytecodePatch( // region patch for restore old player background OldPlayerBackgroundFingerprint.result?.let { - OldPlayerBackgroundFingerprint.literalInstructionBooleanHook( + OldPlayerBackgroundFingerprint.injectLiteralInstructionBooleanCall( 45415319, "$PLAYER_CLASS_DESCRIPTOR->restoreOldPlayerBackground(Z)Z" ) @@ -922,7 +932,7 @@ object PlayerComponentsPatch : BaseBytecodePatch( // region patch for restore old player layout OldPlayerLayoutFingerprint.result?.let { - OldPlayerLayoutFingerprint.literalInstructionBooleanHook( + OldPlayerLayoutFingerprint.injectLiteralInstructionBooleanCall( 45399578, "$PLAYER_CLASS_DESCRIPTOR->restoreOldPlayerLayout(Z)Z" ) @@ -943,11 +953,14 @@ object PlayerComponentsPatch : BaseBytecodePatch( viewId: Long ) { val miniPlayerPlayPauseReplayButtonIndex = - getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton) + indexOfFirstWideLiteralInstructionValueOrThrow(MiniPlayerPlayPauseReplayButton) val miniPlayerPlayPauseReplayButtonRegister = getInstruction(miniPlayerPlayPauseReplayButtonIndex).registerA val findViewByIdIndex = - getTargetIndexOrThrow(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_VIRTUAL) + indexOfFirstInstructionOrThrow( + miniPlayerPlayPauseReplayButtonIndex, + Opcode.INVOKE_VIRTUAL + ) val parentViewRegister = getInstruction(findViewByIdIndex).registerC @@ -966,11 +979,14 @@ object PlayerComponentsPatch : BaseBytecodePatch( viewId: Long ) { val miniPlayerPlayPauseReplayButtonIndex = - getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton) + indexOfFirstWideLiteralInstructionValueOrThrow(MiniPlayerPlayPauseReplayButton) val constRegister = getInstruction(miniPlayerPlayPauseReplayButtonIndex).registerA val findViewByIdIndex = - getTargetIndexOrThrow(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_VIRTUAL) + indexOfFirstInstructionOrThrow( + miniPlayerPlayPauseReplayButtonIndex, + Opcode.INVOKE_VIRTUAL + ) val findViewByIdRegister = getInstruction(findViewByIdIndex).registerC @@ -986,9 +1002,12 @@ object PlayerComponentsPatch : BaseBytecodePatch( private fun MutableMethod.setViewArray() { val miniPlayerPlayPauseReplayButtonIndex = - getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton) + indexOfFirstWideLiteralInstructionValueOrThrow(MiniPlayerPlayPauseReplayButton) val invokeStaticIndex = - getTargetIndexOrThrow(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_STATIC) + indexOfFirstInstructionOrThrow( + miniPlayerPlayPauseReplayButtonIndex, + Opcode.INVOKE_STATIC + ) val viewArrayRegister = getInstruction(invokeStaticIndex).registerC addInstructions( @@ -1005,21 +1024,18 @@ object PlayerComponentsPatch : BaseBytecodePatch( methodName: String, fieldName: String ) { - val startIndex = getStringInstructionIndex(intentString) - val onClickIndex = getTargetIndexReversedOrThrow(startIndex, Opcode.INVOKE_VIRTUAL) + val startIndex = indexOfFirstStringInstructionOrThrow(intentString) + val onClickIndex = indexOfFirstInstructionReversedOrThrow(startIndex, Opcode.INVOKE_VIRTUAL) val onClickReference = getInstruction(onClickIndex).reference val onClickReferenceDefiningClass = (onClickReference as MethodReference).definingClass - val onClickClass = - context.findClass(onClickReferenceDefiningClass)!!.mutableClass - - onClickClass.methods.find { method -> method.name == "" } - ?.apply { + context.findMethodOrThrow(onClickReferenceDefiningClass) + .apply { addInstruction( - implementation!!.instructions.size - 1, + implementation!!.instructions.lastIndex, "sput-object p0, $PLAYER_CLASS_DESCRIPTOR->$fieldName:$onClickReferenceDefiningClass" ) - } ?: throw PatchException("onClickClass not found!") + } PlayerPatchConstructorFingerprint.resultOrThrow().let { val mutableClass = it.mutableClass diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/EngagementPanelHeightFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/EngagementPanelHeightFingerprint.kt new file mode 100644 index 000000000..85111f705 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/EngagementPanelHeightFingerprint.kt @@ -0,0 +1,26 @@ +package app.revanced.patches.music.player.components.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.reference.MethodReference + +internal object EngagementPanelHeightFingerprint : MethodFingerprint( + returnType = "L", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + opcodes = listOf( + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + ), + parameters = emptyList(), + customFingerprint = custom@{ methodDef, _ -> + methodDef.indexOfFirstInstruction { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "booleanValue" + } >= 0 + } +) diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/EngagementPanelHeightParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/EngagementPanelHeightParentFingerprint.kt new file mode 100644 index 000000000..334bbd436 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/EngagementPanelHeightParentFingerprint.kt @@ -0,0 +1,28 @@ +package app.revanced.patches.music.player.components.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.util.indexOfFirstInstruction +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction + +internal object EngagementPanelHeightParentFingerprint : MethodFingerprint( + returnType = "L", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + opcodes = listOf(Opcode.NEW_ARRAY), + parameters = emptyList(), + customFingerprint = custom@{ methodDef, _ -> + if (methodDef.definingClass.startsWith("Lcom/")) { + return@custom false + } + if (methodDef.returnType == "Ljava/lang/Object;") { + return@custom false + } + + methodDef.indexOfFirstInstruction { + opcode == Opcode.CHECK_CAST && + (this as? ReferenceInstruction)?.reference?.toString() == "Lcom/google/android/libraries/youtube/engagementpanel/size/EngagementPanelSizeBehavior;" + } >= 0 + } +) diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MiniPlayerConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MiniPlayerConstructorFingerprint.kt index 3ac11537f..57ec8f975 100644 --- a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MiniPlayerConstructorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MiniPlayerConstructorFingerprint.kt @@ -3,13 +3,13 @@ package app.revanced.patches.music.player.components.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.ColorGrey import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MiniPlayerPlayPauseReplayButton -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue internal object MiniPlayerConstructorFingerprint : MethodFingerprint( returnType = "V", strings = listOf("sharedToggleMenuItemMutations"), customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(ColorGrey) - && methodDef.containsWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton) + methodDef.containsWideLiteralInstructionValue(ColorGrey) + && methodDef.containsWideLiteralInstructionValue(MiniPlayerPlayPauseReplayButton) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MppWatchWhileLayoutFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MppWatchWhileLayoutFingerprint.kt index a7e57557d..5da2c8242 100644 --- a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MppWatchWhileLayoutFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MppWatchWhileLayoutFingerprint.kt @@ -1,16 +1,42 @@ package app.revanced.patches.music.player.components.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.music.player.components.fingerprints.MppWatchWhileLayoutFingerprint.indexOfCallableInstruction import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MiniPlayerPlayPauseReplayButton -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.patches.music.utils.settings.SettingsPatch +import app.revanced.util.containsWideLiteralInstructionValue +import app.revanced.util.getReference +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.reference.MethodReference internal object MppWatchWhileLayoutFingerprint : MethodFingerprint( returnType = "V", opcodes = listOf(Opcode.NEW_ARRAY), - customFingerprint = { methodDef, _ -> - methodDef.definingClass.endsWith("/MppWatchWhileLayout;") - && methodDef.name == "onFinishInflate" - && methodDef.containsWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton) + customFingerprint = custom@{ methodDef, _ -> + if (!methodDef.definingClass.endsWith("/MppWatchWhileLayout;")) { + return@custom false + } + if (methodDef.name != "onFinishInflate") { + return@custom false + } + if (!methodDef.containsWideLiteralInstructionValue(MiniPlayerPlayPauseReplayButton)) { + return@custom false + } + if (!SettingsPatch.upward0718) { + return@custom true + } + + indexOfCallableInstruction(methodDef) >= 0 } -) +) { + fun indexOfCallableInstruction(methodDef: Method) = + methodDef.indexOfFirstInstruction { + val reference = getReference() + opcode == Opcode.INVOKE_VIRTUAL && + reference?.returnType == "V" && + reference.parameterTypes.size == 1 && + reference.parameterTypes.firstOrNull() == "Ljava/util/concurrent/Callable;" + } +} diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MusicActivityWidgetFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MusicActivityWidgetFingerprint.kt index 0eb77a374..32c5106e4 100644 --- a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MusicActivityWidgetFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MusicActivityWidgetFingerprint.kt @@ -1,13 +1,13 @@ package app.revanced.patches.music.player.components.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue internal object MusicActivityWidgetFingerprint : MethodFingerprint( customFingerprint = handler@{ methodDef, _ -> if (!methodDef.definingClass.endsWith("/MusicActivity;")) return@handler false - methodDef.containsWideLiteralInstructionIndex(79500) + methodDef.containsWideLiteralInstructionValue(79500) } ) diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/PlayerViewPagerConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/PlayerViewPagerConstructorFingerprint.kt index 9a2116941..e1ad8bc6b 100644 --- a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/PlayerViewPagerConstructorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/PlayerViewPagerConstructorFingerprint.kt @@ -4,14 +4,14 @@ import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MiniPlayerViewPager import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.PlayerViewPager -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object PlayerViewPagerConstructorFingerprint : MethodFingerprint( returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(MiniPlayerViewPager) - && methodDef.containsWideLiteralInstructionIndex(PlayerViewPager) + methodDef.containsWideLiteralInstructionValue(MiniPlayerViewPager) + && methodDef.containsWideLiteralInstructionValue(PlayerViewPager) }, ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/QuickSeekOverlayFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/QuickSeekOverlayFingerprint.kt index 89714d3b2..1e2add9d4 100644 --- a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/QuickSeekOverlayFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/QuickSeekOverlayFingerprint.kt @@ -3,13 +3,13 @@ package app.revanced.patches.music.player.components.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.DarkBackground import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.TapBloomView -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue internal object QuickSeekOverlayFingerprint : MethodFingerprint( returnType = "V", parameters = emptyList(), customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(DarkBackground) - && methodDef.containsWideLiteralInstructionIndex(TapBloomView) + methodDef.containsWideLiteralInstructionValue(DarkBackground) + && methodDef.containsWideLiteralInstructionValue(TapBloomView) }, ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/ShuffleClassReferenceFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/ShuffleClassReferenceFingerprint.kt deleted file mode 100644 index 64f792f24..000000000 --- a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/ShuffleClassReferenceFingerprint.kt +++ /dev/null @@ -1,39 +0,0 @@ -package app.revanced.patches.music.player.components.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint.indexOfImageViewInstruction -import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint.indexOfOrdinalInstruction -import app.revanced.util.containsWideLiteralInstructionIndex -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstruction -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.Method -import com.android.tools.smali.dexlib2.iface.reference.FieldReference -import com.android.tools.smali.dexlib2.iface.reference.MethodReference - -internal object ShuffleClassReferenceFingerprint : MethodFingerprint( - returnType = "V", - accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, - parameters = emptyList(), - strings = listOf("Unknown shuffle mode"), - customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(45468) && - indexOfOrdinalInstruction(methodDef) >= 0 && - indexOfImageViewInstruction(methodDef) >= 0 - } -) { - fun indexOfOrdinalInstruction(methodDef: Method) = - methodDef.indexOfFirstInstruction { - opcode == Opcode.INVOKE_VIRTUAL && - getReference()?.name == "ordinal" - } - - fun indexOfImageViewInstruction(methodDef: Method) = - methodDef.indexOfFirstInstruction { - opcode == Opcode.IGET_OBJECT && - getReference()?.type == "Landroid/widget/ImageView;" - } -} - diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/ShuffleOnClickFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/ShuffleOnClickFingerprint.kt new file mode 100644 index 000000000..608e713ea --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/ShuffleOnClickFingerprint.kt @@ -0,0 +1,30 @@ +package app.revanced.patches.music.player.components.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.music.player.components.fingerprints.ShuffleOnClickFingerprint.indexOfAccessibilityInstruction +import app.revanced.util.containsWideLiteralInstructionValue +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.MethodReference + +internal object ShuffleOnClickFingerprint : MethodFingerprint( + returnType = "V", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + parameters = listOf("Landroid/view/View;"), + customFingerprint = { methodDef, _ -> + methodDef.containsWideLiteralInstructionValue(45468) && + methodDef.name == "onClick" && + indexOfAccessibilityInstruction(methodDef) >= 0 + } +) { + fun indexOfAccessibilityInstruction(methodDef: Method) = + methodDef.indexOfFirstInstruction { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "announceForAccessibility" + } +} + diff --git a/src/main/kotlin/app/revanced/patches/music/utils/compatibility/Constants.kt b/src/main/kotlin/app/revanced/patches/music/utils/compatibility/Constants.kt index 3cccd72aa..8836730d5 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/compatibility/Constants.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/compatibility/Constants.kt @@ -8,11 +8,10 @@ object Constants { "com.google.android.apps.youtube.music", setOf( "6.20.51", // This is the latest version that supports Android 5.0 - "6.29.58", // This is the latest version that supports the 'Restore old player layout' setting. - "6.33.52", // This is the latest version with the legacy code of YouTube Music. + "6.29.59", // This is the latest version that supports the 'Restore old player layout' setting. "6.42.55", // This is the latest version that supports Android 7.0 "6.51.53", // This is the latest version of YouTube Music 6.xx.xx - "7.16.52", // This is the latest version supported by the RVX patch. + "7.16.53", // This is the latest version supported by the RVX patch. ) ) ) diff --git a/src/main/kotlin/app/revanced/patches/music/utils/fix/accessibility/AccessibilityNodeInfoPatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/fix/accessibility/AccessibilityNodeInfoPatch.kt deleted file mode 100644 index 5dd6b7a7b..000000000 --- a/src/main/kotlin/app/revanced/patches/music/utils/fix/accessibility/AccessibilityNodeInfoPatch.kt +++ /dev/null @@ -1,60 +0,0 @@ -package app.revanced.patches.music.utils.fix.accessibility - -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patches.music.utils.fix.accessibility.fingerprints.TouchExplorationHoverEventFingerprint -import app.revanced.util.containsMethodReferenceNameInstructionIndex -import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction -import com.android.tools.smali.dexlib2.iface.reference.MethodReference - -object AccessibilityNodeInfoPatch : BytecodePatch( - setOf(TouchExplorationHoverEventFingerprint) -) { - override fun execute(context: BytecodeContext) { - - /** - * The "getTouchDelegateInfo" method has been implemented in YT Music v6.44.52. - * For some reason this method sometimes returns null, which throws [IllegalArgumentException]. - * This is considered unimplemented code, so remove all methods associated with it. - */ - TouchExplorationHoverEventFingerprint.result?.let { - it.mutableMethod.apply { - // Target instruction is invoke-static, but can also be invoke-virtual. - // Therefore, the opcode is not checked. - val touchExplorationHoverEventMethodIndex = - implementation!!.instructions.indexOfFirst { instruction -> - val reference = - ((instruction as? ReferenceInstruction)?.reference as? MethodReference) - ((instruction as? ReferenceInstruction)?.reference as? MethodReference)?.definingClass == definingClass - && reference?.returnType == "Z" - } - - // Doesn't raise an exception, even if the target instruction is not found in this method - val touchExplorationHoverEventMethodName = - if (touchExplorationHoverEventMethodIndex > -1) - (getInstruction(touchExplorationHoverEventMethodIndex).reference as MethodReference).name - else - "UNDEFINED" - - val methods = it.mutableClass.methods - - methods.find { method -> - method.name == "getTouchDelegateInfo" - }?.apply { - if (!containsMethodReferenceNameInstructionIndex("isEmpty")) { - arrayOf( - "getTouchDelegateInfo", - name, - touchExplorationHoverEventMethodName - ).forEach { methodName -> - methods.removeIf { method -> - method.name == methodName - } - } - } - } - } - } // If this method has not been added, there is no need to remove it, so it will not raise any exceptions. - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/utils/fix/accessibility/fingerprints/TouchExplorationHoverEventFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/utils/fix/accessibility/fingerprints/TouchExplorationHoverEventFingerprint.kt deleted file mode 100644 index 97920323e..000000000 --- a/src/main/kotlin/app/revanced/patches/music/utils/fix/accessibility/fingerprints/TouchExplorationHoverEventFingerprint.kt +++ /dev/null @@ -1,8 +0,0 @@ -package app.revanced.patches.music.utils.fix.accessibility.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint - -internal object TouchExplorationHoverEventFingerprint : MethodFingerprint( - returnType = "Z", - customFingerprint = { methodDef, _ -> methodDef.name == "onTouchExplorationHoverEvent" } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/utils/fix/header/RestoreOldHeaderPatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/fix/header/RestoreOldHeaderPatch.kt index 907fdeb5f..c95ad1965 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/fix/header/RestoreOldHeaderPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/fix/header/RestoreOldHeaderPatch.kt @@ -1,16 +1,11 @@ package app.revanced.patches.music.utils.fix.header import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.music.layout.header.ChangeHeaderPatch import app.revanced.patches.music.utils.fix.header.fingerprints.HeaderSwitchConfigFingerprint -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getWideLiteralInstructionIndex -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import app.revanced.util.injectLiteralInstructionBooleanCall @Patch( description = "Fix the issues where new headers are used." @@ -31,19 +26,10 @@ object RestoreOldHeaderPatch : BytecodePatch( * TODO: Add a new header image file to [ChangeHeaderPatch] later. */ HeaderSwitchConfigFingerprint.result?.let { - it.mutableMethod.apply { - val targetIndex = - getTargetIndexOrThrow( - getWideLiteralInstructionIndex(45617851), - Opcode.MOVE_RESULT - ) - val targetRegister = getInstruction(targetIndex).registerA - - addInstruction( - targetIndex + 1, - "const/4 v$targetRegister, 0x0" - ) - } + HeaderSwitchConfigFingerprint.injectLiteralInstructionBooleanCall( + 45617851, + "0x0" + ) } } diff --git a/src/main/kotlin/app/revanced/patches/music/utils/flyoutmenu/FlyoutMenuHookPatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/flyoutmenu/FlyoutMenuHookPatch.kt index 37c876d38..53ea63ec3 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/flyoutmenu/FlyoutMenuHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/flyoutmenu/FlyoutMenuHookPatch.kt @@ -6,7 +6,7 @@ import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.music.utils.flyoutmenu.fingerprints.PlaybackRateBottomSheetClassFingerprint import app.revanced.patches.music.utils.integrations.Constants.INTEGRATIONS_PATH import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch -import app.revanced.util.addFieldAndInstructions +import app.revanced.util.addStaticFieldToIntegration import app.revanced.util.resultOrThrow @Patch( @@ -31,15 +31,12 @@ object FlyoutMenuHookPatch : BytecodePatch( return-void """ - context.findClass( - INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR - )!!.mutableClass.addFieldAndInstructions( - context, + context.addStaticFieldToIntegration( + INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR, "showPlaybackSpeedFlyoutMenu", "playbackRateBottomSheetClass", definingClass, - smaliInstructions, - true + smaliInstructions ) } } diff --git a/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt index e911ff8b8..db57d3732 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt @@ -8,6 +8,7 @@ import app.revanced.patches.shared.mapping.ResourceMappingPatch.getId import app.revanced.patches.shared.mapping.ResourceType.BOOL import app.revanced.patches.shared.mapping.ResourceType.COLOR import app.revanced.patches.shared.mapping.ResourceType.DIMEN +import app.revanced.patches.shared.mapping.ResourceType.DRAWABLE import app.revanced.patches.shared.mapping.ResourceType.ID import app.revanced.patches.shared.mapping.ResourceType.LAYOUT import app.revanced.patches.shared.mapping.ResourceType.STRING @@ -32,6 +33,7 @@ object SharedResourceIdPatch : ResourcePatch() { var InterstitialsContainer = -1L var IsTablet = -1L var LikeDislikeContainer = -1L + var MainActivityLaunchAnimation = -1L var MenuEntry = -1L var MiniPlayerDefaultText = -1L var MiniPlayerMdxPlaying = -1L @@ -77,6 +79,7 @@ object SharedResourceIdPatch : ResourcePatch() { InterstitialsContainer = getId(ID, "interstitials_container") IsTablet = getId(BOOL, "is_tablet") LikeDislikeContainer = getId(ID, "like_dislike_container") + MainActivityLaunchAnimation = getId(LAYOUT, "main_activity_launch_animation") MenuEntry = getId(LAYOUT, "menu_entry") MiniPlayerDefaultText = getId(STRING, "mini_player_default_text") MiniPlayerMdxPlaying = getId(STRING, "mini_player_mdx_playing") diff --git a/src/main/kotlin/app/revanced/patches/music/utils/returnyoutubedislike/ReturnYouTubeDislikeBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/returnyoutubedislike/ReturnYouTubeDislikeBytecodePatch.kt index 7c7223d9f..d1ce151c9 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/returnyoutubedislike/ReturnYouTubeDislikeBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/returnyoutubedislike/ReturnYouTubeDislikeBytecodePatch.kt @@ -12,7 +12,7 @@ import app.revanced.patches.music.utils.returnyoutubedislike.fingerprints.Dislik import app.revanced.patches.music.utils.returnyoutubedislike.fingerprints.LikeFingerprint import app.revanced.patches.music.utils.returnyoutubedislike.fingerprints.RemoveLikeFingerprint import app.revanced.patches.music.utils.returnyoutubedislike.fingerprints.TextComponentFingerprint -import app.revanced.patches.music.video.videoid.VideoIdPatch +import app.revanced.patches.music.video.information.VideoInformationPatch import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -22,7 +22,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction @Patch( dependencies = [ SharedResourceIdPatch::class, - VideoIdPatch::class + VideoInformationPatch::class ] ) object ReturnYouTubeDislikeBytecodePatch : BytecodePatch( @@ -70,7 +70,7 @@ object ReturnYouTubeDislikeBytecodePatch : BytecodePatch( } } - VideoIdPatch.hookVideoId("$INTEGRATIONS_RYD_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V") + VideoInformationPatch.videoIdHook("$INTEGRATIONS_RYD_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V") } diff --git a/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsBytecodePatch.kt index d78940ff1..e3a25fead 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsBytecodePatch.kt @@ -17,7 +17,7 @@ import app.revanced.patches.music.utils.settings.fingerprints.PreferenceFingerpr import app.revanced.patches.music.utils.settings.fingerprints.SettingsHeadersFragmentFingerprint import app.revanced.patches.shared.fingerprints.SharedSettingFingerprint import app.revanced.patches.shared.integrations.Constants.INTEGRATIONS_UTILS_CLASS_DESCRIPTOR -import app.revanced.util.getTargetIndexOrThrow +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @@ -52,7 +52,7 @@ object SettingsBytecodePatch : BytecodePatch( */ SharedSettingFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val stringIndex = getTargetIndexOrThrow(Opcode.CONST_STRING) + val stringIndex = indexOfFirstInstructionOrThrow(Opcode.CONST_STRING) val stringRegister = getInstruction(stringIndex).registerA replaceInstruction( diff --git a/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsPatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsPatch.kt index 217f28302..669b2a282 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsPatch.kt @@ -3,7 +3,6 @@ package app.revanced.patches.music.utils.settings import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE -import app.revanced.patches.music.utils.fix.accessibility.AccessibilityNodeInfoPatch import app.revanced.patches.music.utils.settings.ResourceUtils.addPreferenceCategory import app.revanced.patches.music.utils.settings.ResourceUtils.addPreferenceWithIntent import app.revanced.patches.music.utils.settings.ResourceUtils.addRVXSettingsPreference @@ -22,10 +21,7 @@ import java.util.concurrent.TimeUnit object SettingsPatch : BaseResourcePatch( name = "Settings for YouTube Music", description = "Applies mandatory patches to implement ReVanced Extended settings into the application.", - dependencies = setOf( - AccessibilityNodeInfoPatch::class, - SettingsBytecodePatch::class - ), + dependencies = setOf(SettingsBytecodePatch::class), compatiblePackages = COMPATIBLE_PACKAGE, requiresIntegrations = true ), Closeable { @@ -42,8 +38,12 @@ object SettingsPatch : BaseResourcePatch( private lateinit var customName: String lateinit var contexts: ResourceContext + internal var upward0627 = false internal var upward0636 = false internal var upward0642 = false + internal var upward0706 = false + internal var upward0718 = false + internal var upward0720 = false override fun execute(context: ResourceContext) { @@ -136,8 +136,12 @@ object SettingsPatch : BaseResourcePatch( val playServicesVersion = node.textContent.toInt() + upward0627 = 234412000 <= playServicesVersion upward0636 = 240399000 <= playServicesVersion upward0642 = 240999000 <= playServicesVersion + upward0706 = 242499000 <= playServicesVersion + upward0718 = 243699000 <= playServicesVersion + upward0720 = 243899000 <= playServicesVersion break } @@ -240,6 +244,14 @@ object SettingsPatch : BaseResourcePatch( } } + /** + * add open default app settings + */ + addPreferenceWithIntent( + CategoryType.MISC, + "revanced_default_app_settings" + ) + /** * add import export settings */ diff --git a/src/main/kotlin/app/revanced/patches/music/utils/sponsorblock/SponsorBlockBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/sponsorblock/SponsorBlockBytecodePatch.kt index adce2aba8..6f6cb84b3 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/sponsorblock/SponsorBlockBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/sponsorblock/SponsorBlockBytecodePatch.kt @@ -6,27 +6,30 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.music.utils.fingerprints.SeekBarConstructorFingerprint import app.revanced.patches.music.utils.integrations.Constants.INTEGRATIONS_PATH import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.music.utils.sponsorblock.fingerprints.MusicPlaybackControlsTimeBarDrawFingerprint import app.revanced.patches.music.utils.sponsorblock.fingerprints.MusicPlaybackControlsTimeBarOnMeasureFingerprint +import app.revanced.patches.music.utils.sponsorblock.fingerprints.RectangleFieldInvalidatorFingerprint +import app.revanced.patches.music.utils.sponsorblock.fingerprints.SeekBarConstructorFingerprint import app.revanced.patches.music.utils.sponsorblock.fingerprints.SeekbarOnDrawFingerprint import app.revanced.patches.music.video.information.VideoInformationPatch -import app.revanced.patches.music.video.videoid.VideoIdPatch -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameReversedOrThrow +import app.revanced.util.alsoResolve +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode 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.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Patch( dependencies = [ SharedResourceIdPatch::class, - VideoInformationPatch::class, - VideoIdPatch::class + VideoInformationPatch::class ] ) object SponsorBlockBytecodePatch : BytecodePatch( @@ -39,7 +42,6 @@ object SponsorBlockBytecodePatch : BytecodePatch( private const val INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR = "$INTEGRATIONS_PATH/sponsorblock/SegmentPlaybackController;" - private lateinit var rectangleFieldName: String override fun execute(context: BytecodeContext) { /** @@ -55,22 +57,41 @@ object SponsorBlockBytecodePatch : BytecodePatch( /** * Responsible for seekbar in fullscreen */ - val seekBarClass = SeekBarConstructorFingerprint.resultOrThrow().mutableClass - SeekbarOnDrawFingerprint.resolve(context, seekBarClass) + var rectangleFieldName = + RectangleFieldInvalidatorFingerprint.alsoResolve( + context, SeekBarConstructorFingerprint + ).let { + with(it.mutableMethod) { + val invalidateIndex = + RectangleFieldInvalidatorFingerprint.indexOfInvalidateInstruction(this) + val rectangleIndex = + indexOfFirstInstructionReversedOrThrow(invalidateIndex + 1) { + getReference()?.type == "Landroid/graphics/Rect;" + } + val rectangleReference = + getInstruction(rectangleIndex).reference - SeekbarOnDrawFingerprint.resultOrThrow().let { + (rectangleReference as FieldReference).name + } + } + + SeekbarOnDrawFingerprint.alsoResolve( + context, SeekBarConstructorFingerprint + ).let { it.mutableMethod.apply { // Initialize seekbar method addInstructions( 0, """ move-object/from16 v0, p0 - const-string v1, "${VideoInformationPatch.rectangleFieldName}" + const-string v1, "$rectangleFieldName" invoke-static {v0, v1}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;Ljava/lang/String;)V """ ) // Set seekbar thickness - val roundIndex = getTargetIndexWithMethodReferenceNameOrThrow("round") + 1 + val roundIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "round" + } + 1 val roundRegister = getInstruction(roundIndex).registerA addInstruction( roundIndex + 1, @@ -79,8 +100,9 @@ object SponsorBlockBytecodePatch : BytecodePatch( ) // Draw segment - val drawCircleIndex = - getTargetIndexWithMethodReferenceNameReversedOrThrow("drawCircle") + val drawCircleIndex = indexOfFirstInstructionReversedOrThrow { + getReference()?.name == "drawCircle" + } val drawCircleInstruction = getInstruction(drawCircleIndex) addInstruction( drawCircleIndex, @@ -94,14 +116,15 @@ object SponsorBlockBytecodePatch : BytecodePatch( /** * Responsible for seekbar in player */ - MusicPlaybackControlsTimeBarOnMeasureFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - val rectangleIndex = it.scanResult.patternScanResult!!.startIndex - val rectangleReference = - getInstruction(rectangleIndex).reference - rectangleFieldName = (rectangleReference as FieldReference).name + rectangleFieldName = + MusicPlaybackControlsTimeBarOnMeasureFingerprint.resultOrThrow().let { + with(it.mutableMethod) { + val rectangleIndex = it.scanResult.patternScanResult!!.startIndex + val rectangleReference = + getInstruction(rectangleIndex).reference + (rectangleReference as FieldReference).name + } } - } MusicPlaybackControlsTimeBarDrawFingerprint.resultOrThrow().let { it.mutableMethod.apply { @@ -115,7 +138,10 @@ object SponsorBlockBytecodePatch : BytecodePatch( ) // Draw segment - val drawCircleIndex = getTargetIndexWithMethodReferenceNameOrThrow("drawCircle") + val drawCircleIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL + && getReference()?.name == "drawCircle" + } val drawCircleInstruction = getInstruction(drawCircleIndex) addInstruction( drawCircleIndex, @@ -128,6 +154,6 @@ object SponsorBlockBytecodePatch : BytecodePatch( /** * Set current video id */ - VideoIdPatch.hookVideoId("$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setVideoId(Ljava/lang/String;)V") + VideoInformationPatch.videoIdHook("$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setVideoId(Ljava/lang/String;)V") } } diff --git a/src/main/kotlin/app/revanced/patches/music/utils/sponsorblock/fingerprints/RectangleFieldInvalidatorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/utils/sponsorblock/fingerprints/RectangleFieldInvalidatorFingerprint.kt new file mode 100644 index 000000000..3e779cccc --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/utils/sponsorblock/fingerprints/RectangleFieldInvalidatorFingerprint.kt @@ -0,0 +1,28 @@ +package app.revanced.patches.music.utils.sponsorblock.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.music.utils.sponsorblock.fingerprints.RectangleFieldInvalidatorFingerprint.indexOfInvalidateInstruction +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionReversed +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.MethodReference + +internal object RectangleFieldInvalidatorFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_WIDE, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_WIDE, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_WIDE + ), + customFingerprint = { methodDef, _ -> + indexOfInvalidateInstruction(methodDef) >= 0 + } +) { + fun indexOfInvalidateInstruction(methodDef: Method) = + methodDef.indexOfFirstInstructionReversed { + getReference()?.name == "invalidate" + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/utils/fingerprints/SeekBarConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/utils/sponsorblock/fingerprints/SeekBarConstructorFingerprint.kt similarity index 82% rename from src/main/kotlin/app/revanced/patches/music/utils/fingerprints/SeekBarConstructorFingerprint.kt rename to src/main/kotlin/app/revanced/patches/music/utils/sponsorblock/fingerprints/SeekBarConstructorFingerprint.kt index cf5d9a27f..9edfd4c98 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/fingerprints/SeekBarConstructorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/sponsorblock/fingerprints/SeekBarConstructorFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.music.utils.fingerprints +package app.revanced.patches.music.utils.sponsorblock.fingerprints import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.InlineTimeBarAdBreakMarkerColor import app.revanced.util.fingerprint.LiteralValueFingerprint diff --git a/src/main/kotlin/app/revanced/patches/music/video/information/VideoInformationPatch.kt b/src/main/kotlin/app/revanced/patches/music/video/information/VideoInformationPatch.kt index 53cd1e098..8dd9730a7 100644 --- a/src/main/kotlin/app/revanced/patches/music/video/information/VideoInformationPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/video/information/VideoInformationPatch.kt @@ -4,40 +4,36 @@ import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprintResult import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patcher.util.proxy.mutableTypes.MutableClass import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.util.smali.toInstructions -import app.revanced.patches.music.utils.fingerprints.SeekBarConstructorFingerprint import app.revanced.patches.music.utils.integrations.Constants.SHARED_PATH import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.music.video.information.fingerprints.PlaybackSpeedFingerprint import app.revanced.patches.music.video.information.fingerprints.PlaybackSpeedParentFingerprint import app.revanced.patches.music.video.information.fingerprints.PlayerControllerSetTimeReferenceFingerprint import app.revanced.patches.music.video.information.fingerprints.VideoEndFingerprint -import app.revanced.patches.music.video.information.fingerprints.VideoLengthFingerprint +import app.revanced.patches.music.video.information.fingerprints.VideoIdFingerprint import app.revanced.patches.music.video.information.fingerprints.VideoQualityListFingerprint import app.revanced.patches.music.video.information.fingerprints.VideoQualityTextFingerprint -import app.revanced.patches.music.video.videoid.VideoIdPatch import app.revanced.patches.shared.fingerprints.MdxPlayerDirectorSetVideoStageFingerprint -import app.revanced.util.addFieldAndInstructions +import app.revanced.patches.shared.fingerprints.VideoLengthFingerprint +import app.revanced.util.addStaticFieldToIntegration +import app.revanced.util.alsoResolve import app.revanced.util.getReference -import app.revanced.util.getTargetIndexWithFieldReferenceTypeReversedOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameReversedOrThrow import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode 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.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction -import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.immutable.ImmutableMethodImplementation @@ -45,10 +41,7 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter import com.android.tools.smali.dexlib2.util.MethodUtil @Patch( - dependencies = [ - SharedResourceIdPatch::class, - VideoIdPatch::class - ] + dependencies = [SharedResourceIdPatch::class] ) @Suppress("MemberVisibilityCanBePrivate") object VideoInformationPatch : BytecodePatch( @@ -56,8 +49,9 @@ object VideoInformationPatch : BytecodePatch( MdxPlayerDirectorSetVideoStageFingerprint, PlayerControllerSetTimeReferenceFingerprint, PlaybackSpeedParentFingerprint, - SeekBarConstructorFingerprint, VideoEndFingerprint, + VideoIdFingerprint, + VideoLengthFingerprint, VideoQualityListFingerprint, VideoQualityTextFingerprint ) @@ -65,6 +59,20 @@ object VideoInformationPatch : BytecodePatch( private const val INTEGRATIONS_CLASS_DESCRIPTOR = "$SHARED_PATH/VideoInformation;" + private const val REGISTER_PLAYER_RESPONSE_MODEL = 4 + + private const val REGISTER_VIDEO_ID = 0 + private const val REGISTER_VIDEO_LENGTH = 1 + + @Suppress("unused") + private const val REGISTER_VIDEO_LENGTH_DUMMY = 2 + + private lateinit var PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR: String + private lateinit var videoIdMethodCall: String + private lateinit var videoLengthMethodCall: String + + private lateinit var videoInformationMethod: MutableMethod + /** * Used in [VideoEndFingerprint] and [MdxPlayerDirectorSetVideoStageFingerprint]. * Since both classes are inherited from the same class, @@ -73,7 +81,6 @@ object VideoInformationPatch : BytecodePatch( private var seekSourceEnumType = "" private var seekSourceMethodName = "" - private lateinit var videoInformationMutableClass: MutableClass private lateinit var context: BytecodeContext private lateinit var playerConstructorMethod: MutableMethod @@ -86,7 +93,6 @@ object VideoInformationPatch : BytecodePatch( private var videoTimeConstructorInsertIndex = 2 // Used by other patches. - lateinit var rectangleFieldName: String internal lateinit var playbackSpeedResult: MethodFingerprintResult private fun addSeekInterfaceMethods( @@ -109,7 +115,7 @@ object VideoInformationPatch : BytecodePatch( 4, """ # first enum (field a) is SEEK_SOURCE_UNKNOWN sget-object v0, $seekSourceEnumType->a:$seekSourceEnumType - invoke-virtual {p0, p1, p2, v0}, ${definingClass}->$seekMethodName(J$seekSourceEnumType)Z + invoke-virtual {p0, p1, p2, v0}, $definingClass->$seekMethodName(J$seekSourceEnumType)Z move-result p1 return p1 """.toInstructions(), @@ -130,21 +136,18 @@ object VideoInformationPatch : BytecodePatch( return v0 """ - videoInformationMutableClass.addFieldAndInstructions( - context, + context.addStaticFieldToIntegration( + INTEGRATIONS_CLASS_DESCRIPTOR, methodName, fieldName, definingClass, - smaliInstructions, - true + smaliInstructions ) } } override fun execute(context: BytecodeContext) { this.context = context - videoInformationMutableClass = - context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass VideoEndFingerprint.resultOrThrow().let { it.mutableMethod.apply { @@ -194,6 +197,34 @@ object VideoInformationPatch : BytecodePatch( } } + /** + * Set current video information + */ + VideoIdFingerprint.resultOrThrow().let { + it.mutableMethod.apply { + val playerResponseModelIndex = it.scanResult.patternScanResult!!.startIndex + + PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR = + getInstruction(playerResponseModelIndex) + .getReference() + ?.definingClass + ?: throw PatchException("Could not find Player Response Model class") + + videoIdMethodCall = + VideoIdFingerprint.getPlayerResponseInstruction("Ljava/lang/String;") + videoLengthMethodCall = + VideoLengthFingerprint.getPlayerResponseInstruction("J") + + videoInformationMethod = getVideoInformationMethod() + it.mutableClass.methods.add(videoInformationMethod) + + addInstruction( + playerResponseModelIndex + 2, + "invoke-direct/range {p0 .. p1}, $definingClass->setVideoInformation($PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR)V" + ) + } + } + /** * Set the video time method */ @@ -210,47 +241,19 @@ object VideoInformationPatch : BytecodePatch( /** * Set current video length */ - VideoLengthFingerprint.resolve( - context, - SeekBarConstructorFingerprint.resultOrThrow().classDef - ) - VideoLengthFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - val invalidateIndex = - getTargetIndexWithMethodReferenceNameReversedOrThrow("invalidate") - val rectangleIndex = getTargetIndexWithFieldReferenceTypeReversedOrThrow( - invalidateIndex + 1, - "Landroid/graphics/Rect;" - ) - rectangleFieldName = - (getInstruction(rectangleIndex).reference as FieldReference).name - - val videoLengthRegisterIndex = it.scanResult.patternScanResult!!.startIndex + 1 - val videoLengthRegister = - getInstruction(videoLengthRegisterIndex).registerA - val dummyRegisterForLong = - videoLengthRegister + 1 // required for long values since they are wide - - addInstruction( - videoLengthRegisterIndex + 1, - "invoke-static {v$videoLengthRegister, v$dummyRegisterForLong}, $INTEGRATIONS_CLASS_DESCRIPTOR->setVideoLength(J)V" - ) - } - } + videoLengthHook("$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoLength(J)V") /** * Set current video id */ - VideoIdPatch.hookVideoId("$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoId(Ljava/lang/String;)V") + videoIdHook("$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoId(Ljava/lang/String;)V") /** * Hook current playback speed */ - PlaybackSpeedFingerprint.resolve( - context, - PlaybackSpeedParentFingerprint.resultOrThrow().classDef - ) - PlaybackSpeedFingerprint.resultOrThrow().let { + PlaybackSpeedFingerprint.alsoResolve( + context, PlaybackSpeedParentFingerprint + ).let { it.mutableMethod.apply { playbackSpeedResult = it val endIndex = it.scanResult.patternScanResult!!.endIndex @@ -294,13 +297,12 @@ object VideoInformationPatch : BytecodePatch( return-void """ - videoInformationMutableClass.addFieldAndInstructions( - context, + VideoInformationPatch.context.addStaticFieldToIntegration( + INTEGRATIONS_CLASS_DESCRIPTOR, "overrideVideoQuality", "videoQualityClass", videoQualityClass, - smaliInstructions, - true + smaliInstructions ) } @@ -318,6 +320,49 @@ object VideoInformationPatch : BytecodePatch( } } + private fun MethodFingerprint.getPlayerResponseInstruction(returnType: String): String { + resultOrThrow().mutableMethod.apply { + val targetReference = getInstruction( + indexOfFirstInstructionOrThrow { + val reference = getReference() + (opcode == Opcode.INVOKE_INTERFACE_RANGE || opcode == Opcode.INVOKE_INTERFACE) && + reference?.definingClass == PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR && + reference.returnType == returnType + } + ).reference + + return "invoke-interface/range {v$REGISTER_PLAYER_RESPONSE_MODEL .. v$REGISTER_PLAYER_RESPONSE_MODEL}, $targetReference" + } + } + + private fun MutableMethod.getVideoInformationMethod(): MutableMethod = + ImmutableMethod( + definingClass, + "setVideoInformation", + listOf( + ImmutableMethodParameter( + PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR, + annotations, + null + ) + ), + "V", + AccessFlags.PRIVATE or AccessFlags.FINAL, + annotations, + null, + ImmutableMethodImplementation( + REGISTER_PLAYER_RESPONSE_MODEL + 1, """ + $videoIdMethodCall + move-result-object v$REGISTER_VIDEO_ID + $videoLengthMethodCall + move-result-wide v$REGISTER_VIDEO_LENGTH + return-void + """.toInstructions(), + null, + null + ) + ).toMutable() + private fun MutableMethod.insert(insertIndex: Int, register: String, descriptor: String) = addInstruction(insertIndex, "invoke-static { $register }, $descriptor") @@ -351,6 +396,24 @@ object VideoInformationPatch : BytecodePatch( "invoke-static { }, $targetMethodClass->$targetMethodName()V" ) + internal fun videoIdHook( + descriptor: String + ) = videoInformationMethod.apply { + addInstruction( + implementation!!.instructions.lastIndex, + "invoke-static {v$REGISTER_VIDEO_ID}, $descriptor" + ) + } + + internal fun videoLengthHook( + descriptor: String + ) = videoInformationMethod.apply { + addInstruction( + implementation!!.instructions.lastIndex, + "invoke-static {v$REGISTER_VIDEO_LENGTH, v$REGISTER_VIDEO_LENGTH_DUMMY}, $descriptor" + ) + } + /** * Hook the video time. * The hook is usually called once per second. diff --git a/src/main/kotlin/app/revanced/patches/music/video/videoid/fingerprints/VideoIdFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/video/information/fingerprints/VideoIdFingerprint.kt similarity index 90% rename from src/main/kotlin/app/revanced/patches/music/video/videoid/fingerprints/VideoIdFingerprint.kt rename to src/main/kotlin/app/revanced/patches/music/video/information/fingerprints/VideoIdFingerprint.kt index bc75a0302..5f901dc11 100644 --- a/src/main/kotlin/app/revanced/patches/music/video/videoid/fingerprints/VideoIdFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/video/information/fingerprints/VideoIdFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.music.video.videoid.fingerprints +package app.revanced.patches.music.video.information.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/music/video/information/fingerprints/VideoLengthFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/video/information/fingerprints/VideoLengthFingerprint.kt deleted file mode 100644 index 09da6b37d..000000000 --- a/src/main/kotlin/app/revanced/patches/music/video/information/fingerprints/VideoLengthFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.music.video.information.fingerprints - -import app.revanced.util.fingerprint.MethodReferenceNameFingerprint -import com.android.tools.smali.dexlib2.Opcode - -internal object VideoLengthFingerprint : MethodReferenceNameFingerprint( - opcodes = listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_WIDE, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_WIDE, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_WIDE - ), - reference = { "invalidate" } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/video/playback/VideoPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/music/video/playback/VideoPlaybackPatch.kt index 4173158b0..6c58a8c67 100644 --- a/src/main/kotlin/app/revanced/patches/music/video/playback/VideoPlaybackPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/video/playback/VideoPlaybackPatch.kt @@ -12,13 +12,13 @@ import app.revanced.patches.music.utils.settings.SettingsPatch import app.revanced.patches.music.video.information.VideoInformationPatch import app.revanced.patches.music.video.playback.fingerprints.PlaybackSpeedBottomSheetFingerprint import app.revanced.patches.music.video.playback.fingerprints.UserQualityChangeFingerprint -import app.revanced.patches.music.video.videoid.VideoIdPatch -import app.revanced.util.getTargetIndexOrThrow +import app.revanced.util.findMethodOrThrow +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21c import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction @Suppress("unused") @@ -29,7 +29,6 @@ object VideoPlaybackPatch : BaseBytecodePatch( dependencies = setOf( CustomPlaybackSpeedPatch::class, SettingsPatch::class, - VideoIdPatch::class, VideoInformationPatch::class ), compatiblePackages = COMPATIBLE_PACKAGE, @@ -52,7 +51,7 @@ object VideoPlaybackPatch : BaseBytecodePatch( it.mutableClass.methods.find { method -> method.name == "onItemClick" } onItemClickMethod?.apply { - val targetIndex = getTargetIndexOrThrow(Opcode.IGET) + val targetIndex = indexOfFirstInstructionOrThrow(Opcode.IGET) val targetRegister = getInstruction(targetIndex).registerA @@ -86,23 +85,18 @@ object VideoPlaybackPatch : BaseBytecodePatch( it.mutableMethod.apply { val endIndex = it.scanResult.patternScanResult!!.endIndex val qualityChangedClass = - context.findClass( - (getInstruction(endIndex)) - .reference.toString() - )!! - .mutableClass + getInstruction(endIndex).reference.toString() - val onItemClickMethod = - qualityChangedClass.methods.find { method -> method.name == "onItemClick" } - - onItemClickMethod?.addInstruction( + context.findMethodOrThrow(qualityChangedClass) { + name == "onItemClick" + }.addInstruction( 0, "invoke-static {}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->userSelectedVideoQuality()V" - ) ?: throw PatchException("Failed to find onItemClick method") + ) } } - VideoIdPatch.hookVideoId("$INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;)V") + VideoInformationPatch.videoIdHook("$INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;)V") // endregion diff --git a/src/main/kotlin/app/revanced/patches/music/video/videoid/VideoIdPatch.kt b/src/main/kotlin/app/revanced/patches/music/video/videoid/VideoIdPatch.kt deleted file mode 100644 index 85c190197..000000000 --- a/src/main/kotlin/app/revanced/patches/music/video/videoid/VideoIdPatch.kt +++ /dev/null @@ -1,38 +0,0 @@ -package app.revanced.patches.music.video.videoid - -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.music.video.videoid.fingerprints.VideoIdFingerprint -import app.revanced.util.resultOrThrow -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction - -object VideoIdPatch : BytecodePatch( - setOf(VideoIdFingerprint) -) { - private var videoIdRegister = 0 - private var videoIdInsertIndex = 0 - private lateinit var videoIdMethod: MutableMethod - - override fun execute(context: BytecodeContext) { - - VideoIdFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - videoIdMethod = this - videoIdInsertIndex = it.scanResult.patternScanResult!!.startIndex + 2 - videoIdRegister = - getInstruction(videoIdInsertIndex - 1).registerA - } - } - } - - fun hookVideoId( - methodDescriptor: String - ) = videoIdMethod.addInstruction( - videoIdInsertIndex++, - "invoke-static {v$videoIdRegister}, $methodDescriptor" - ) -} - diff --git a/src/main/kotlin/app/revanced/patches/reddit/ad/general/AdsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/ad/general/AdsPatch.kt index de989f069..dd2595576 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/ad/general/AdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/ad/general/AdsPatch.kt @@ -12,12 +12,15 @@ import app.revanced.patches.reddit.utils.compatibility.Constants.COMPATIBLE_PACK import app.revanced.patches.reddit.utils.integrations.Constants.PATCHES_PATH import app.revanced.patches.reddit.utils.settings.SettingsBytecodePatch.updateSettingsStatus import app.revanced.patches.reddit.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexWithFieldReferenceNameOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction 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.MethodReference @Suppress("unused") object AdsPatch : BaseBytecodePatch( @@ -42,7 +45,9 @@ object AdsPatch : BaseBytecodePatch( // region Filter promoted ads (does not work in popular or latest feed) AdPostFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val targetIndex = getTargetIndexWithFieldReferenceNameOrThrow("children") + val targetIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "children" + } val targetRegister = getInstruction(targetIndex).registerA addInstructions( @@ -59,7 +64,10 @@ object AdsPatch : BaseBytecodePatch( // By removing the appending instruction no ad posts gets appended to the feed. NewAdPostFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val targetIndex = getTargetIndexWithMethodReferenceNameOrThrow("add") + val targetIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL + && getReference()?.toString() == "Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z" + } val targetInstruction = getInstruction(targetIndex) replaceInstruction( diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/recentlyvisited/RecentlyVisitedShelfPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/recentlyvisited/RecentlyVisitedShelfPatch.kt index d9338e274..8956f23e0 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/layout/recentlyvisited/RecentlyVisitedShelfPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/layout/recentlyvisited/RecentlyVisitedShelfPatch.kt @@ -9,15 +9,15 @@ import app.revanced.patches.reddit.utils.compatibility.Constants.COMPATIBLE_PACK import app.revanced.patches.reddit.utils.integrations.Constants.PATCHES_PATH import app.revanced.patches.reddit.utils.settings.SettingsBytecodePatch.updateSettingsStatus import app.revanced.patches.reddit.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.getTargetIndexWithFieldReferenceNameOrThrow -import app.revanced.util.getTargetIndexWithReferenceOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.Reference @Suppress("unused") @@ -40,20 +40,31 @@ object RecentlyVisitedShelfPatch : BaseBytecodePatch( it.mutableClass.methods.find { method -> method.name == "" } ?.apply { - val recentlyVisitedFieldIndex = - getTargetIndexWithFieldReferenceNameOrThrow("RECENTLY_VISITED") + val recentlyVisitedFieldIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "RECENTLY_VISITED" + } val recentlyVisitedObjectIndex = - getTargetIndexOrThrow(recentlyVisitedFieldIndex, Opcode.IPUT_OBJECT) + indexOfFirstInstructionOrThrow( + recentlyVisitedFieldIndex, + Opcode.IPUT_OBJECT + ) recentlyVisitedReference = getInstruction(recentlyVisitedObjectIndex).reference } ?: throw PatchException("Constructor method not found!") it.mutableMethod.apply { - val recentlyVisitedObjectIndex = - getTargetIndexWithReferenceOrThrow(recentlyVisitedReference.toString()) + val recentlyVisitedObjectIndex = indexOfFirstInstructionOrThrow { + getReference()?.toString() == recentlyVisitedReference.toString() + } arrayOf( - getTargetIndexOrThrow(recentlyVisitedObjectIndex, Opcode.INVOKE_STATIC), - getTargetIndexReversedOrThrow(recentlyVisitedObjectIndex, Opcode.INVOKE_STATIC) + indexOfFirstInstructionOrThrow( + recentlyVisitedObjectIndex, + Opcode.INVOKE_STATIC + ), + indexOfFirstInstructionReversedOrThrow( + recentlyVisitedObjectIndex, + Opcode.INVOKE_STATIC + ) ).forEach { staticIndex -> val insertRegister = getInstruction(staticIndex + 1).registerA diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/screenshotpopup/fingerprints/ScreenshotTakenBannerFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/screenshotpopup/fingerprints/ScreenshotTakenBannerFingerprint.kt index 541efade0..6154e8669 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/layout/screenshotpopup/fingerprints/ScreenshotTakenBannerFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/layout/screenshotpopup/fingerprints/ScreenshotTakenBannerFingerprint.kt @@ -3,14 +3,14 @@ package app.revanced.patches.reddit.layout.screenshotpopup.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch.ScreenShotShareBanner -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object ScreenshotTakenBannerFingerprint : MethodFingerprint( returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, customFingerprint = { methodDef, classDef -> - methodDef.containsWideLiteralInstructionIndex(ScreenShotShareBanner) + methodDef.containsWideLiteralInstructionValue(ScreenShotShareBanner) && classDef.sourceFile == "ScreenshotTakenBanner.kt" } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/SubRedditDialogPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/SubRedditDialogPatch.kt index ebc2f2e65..83adfb7b0 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/SubRedditDialogPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/SubRedditDialogPatch.kt @@ -12,7 +12,7 @@ import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch.Cancel import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch.TextAppearanceRedditBaseOldButtonColored import app.revanced.patches.reddit.utils.settings.SettingsBytecodePatch.updateSettingsStatus import app.revanced.patches.reddit.utils.settings.SettingsPatch -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @@ -39,7 +39,8 @@ object SubRedditDialogPatch : BaseBytecodePatch( FrequentUpdatesSheetScreenFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val cancelButtonViewIndex = getWideLiteralInstructionIndex(CancelButton) + 2 + val cancelButtonViewIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(CancelButton) + 2 val cancelButtonViewRegister = getInstruction(cancelButtonViewIndex).registerA @@ -53,7 +54,9 @@ object SubRedditDialogPatch : BaseBytecodePatch( RedditAlertDialogsFingerprint.resultOrThrow().let { it.mutableMethod.apply { val insertIndex = - getWideLiteralInstructionIndex(TextAppearanceRedditBaseOldButtonColored) + 1 + indexOfFirstWideLiteralInstructionValueOrThrow( + TextAppearanceRedditBaseOldButtonColored + ) + 1 val insertRegister = getInstruction(insertIndex).registerC addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/fingerprints/FrequentUpdatesSheetScreenFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/fingerprints/FrequentUpdatesSheetScreenFingerprint.kt index 33e648aac..ab8942a7b 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/fingerprints/FrequentUpdatesSheetScreenFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/fingerprints/FrequentUpdatesSheetScreenFingerprint.kt @@ -3,14 +3,14 @@ package app.revanced.patches.reddit.layout.subredditdialog.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch.CancelButton -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object FrequentUpdatesSheetScreenFingerprint : MethodFingerprint( returnType = "Landroid/view/View;", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, customFingerprint = { methodDef, classDef -> - methodDef.containsWideLiteralInstructionIndex(CancelButton) + methodDef.containsWideLiteralInstructionValue(CancelButton) && classDef.sourceFile == "FrequentUpdatesSheetScreen.kt" } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/fingerprints/RedditAlertDialogsFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/fingerprints/RedditAlertDialogsFingerprint.kt index 44515f97b..a992cad69 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/fingerprints/RedditAlertDialogsFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/fingerprints/RedditAlertDialogsFingerprint.kt @@ -3,14 +3,14 @@ package app.revanced.patches.reddit.layout.subredditdialog.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch.TextAppearanceRedditBaseOldButtonColored -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object RedditAlertDialogsFingerprint : MethodFingerprint( returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, customFingerprint = { methodDef, classDef -> - methodDef.containsWideLiteralInstructionIndex(TextAppearanceRedditBaseOldButtonColored) + methodDef.containsWideLiteralInstructionValue(TextAppearanceRedditBaseOldButtonColored) && classDef.sourceFile == "RedditAlertDialogs.kt" } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/toolbar/ToolBarButtonPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/toolbar/ToolBarButtonPatch.kt index d71fc2f39..f2a305f20 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/layout/toolbar/ToolBarButtonPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/layout/toolbar/ToolBarButtonPatch.kt @@ -10,7 +10,7 @@ import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch.ToolBarNavSearchCtaContainer import app.revanced.patches.reddit.utils.settings.SettingsBytecodePatch.updateSettingsStatus import app.revanced.patches.reddit.utils.settings.SettingsPatch -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @@ -35,7 +35,7 @@ object ToolBarButtonPatch : BaseBytecodePatch( HomePagerScreenFingerprint.resultOrThrow().let { it.mutableMethod.apply { val targetIndex = - getWideLiteralInstructionIndex(ToolBarNavSearchCtaContainer) + 3 + indexOfFirstWideLiteralInstructionValueOrThrow(ToolBarNavSearchCtaContainer) + 3 val targetRegister = getInstruction(targetIndex - 1).registerA diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/toolbar/fingerprints/HomePagerScreenFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/toolbar/fingerprints/HomePagerScreenFingerprint.kt index 4f42a5df8..ecec1bce5 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/layout/toolbar/fingerprints/HomePagerScreenFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/layout/toolbar/fingerprints/HomePagerScreenFingerprint.kt @@ -3,7 +3,7 @@ package app.revanced.patches.reddit.layout.toolbar.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch.ToolBarNavSearchCtaContainer -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object HomePagerScreenFingerprint : MethodFingerprint( @@ -12,6 +12,6 @@ internal object HomePagerScreenFingerprint : MethodFingerprint( parameters = listOf("Landroid/view/LayoutInflater;", "Landroid/view/ViewGroup;"), customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("/HomePagerScreen;") - && methodDef.containsWideLiteralInstructionIndex(ToolBarNavSearchCtaContainer) + && methodDef.containsWideLiteralInstructionValue(ToolBarNavSearchCtaContainer) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/reddit/misc/openlink/OpenLinksExternallyPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/misc/openlink/OpenLinksExternallyPatch.kt index fb1850579..5a9e81681 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/misc/openlink/OpenLinksExternallyPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/misc/openlink/OpenLinksExternallyPatch.kt @@ -9,7 +9,7 @@ import app.revanced.patches.reddit.utils.compatibility.Constants.COMPATIBLE_PACK import app.revanced.patches.reddit.utils.integrations.Constants.PATCHES_PATH import app.revanced.patches.reddit.utils.settings.SettingsBytecodePatch.updateSettingsStatus import app.revanced.patches.reddit.utils.settings.SettingsPatch -import app.revanced.util.getStringInstructionIndex +import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow @@ -27,7 +27,7 @@ object OpenLinksExternallyPatch : BaseBytecodePatch( override fun execute(context: BytecodeContext) { ScreenNavigatorFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = getStringInstructionIndex("uri") + 2 + val insertIndex = indexOfFirstStringInstructionOrThrow("uri") + 2 addInstructionsWithLabels( insertIndex, """ diff --git a/src/main/kotlin/app/revanced/patches/reddit/utils/settings/SettingsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/reddit/utils/settings/SettingsBytecodePatch.kt index cf6aa5851..cd1513922 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/utils/settings/SettingsBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/utils/settings/SettingsBytecodePatch.kt @@ -15,8 +15,8 @@ import app.revanced.patches.reddit.utils.settings.fingerprints.AcknowledgementsL import app.revanced.patches.reddit.utils.settings.fingerprints.OssLicensesMenuActivityOnCreateFingerprint import app.revanced.patches.reddit.utils.settings.fingerprints.SettingsStatusLoadFingerprint import app.revanced.patches.shared.fingerprints.SharedSettingFingerprint -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @@ -39,7 +39,7 @@ object SettingsBytecodePatch : BytecodePatch( internal fun updateSettingsLabel(label: String) = acknowledgementsLabelBuilderMethod.apply { val insertIndex = - getWideLiteralInstructionIndex(LabelAcknowledgements) + 3 + indexOfFirstWideLiteralInstructionValueOrThrow(LabelAcknowledgements) + 3 val insertRegister = getInstruction(insertIndex - 1).registerA @@ -62,7 +62,7 @@ object SettingsBytecodePatch : BytecodePatch( */ SharedSettingFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val stringIndex = getTargetIndexOrThrow(Opcode.CONST_STRING) + val stringIndex = indexOfFirstInstructionOrThrow(Opcode.CONST_STRING) val stringRegister = getInstruction(stringIndex).registerA replaceInstruction( diff --git a/src/main/kotlin/app/revanced/patches/reddit/utils/settings/fingerprints/AcknowledgementsLabelBuilderFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/utils/settings/fingerprints/AcknowledgementsLabelBuilderFingerprint.kt index 6954a037c..6bccc6594 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/utils/settings/fingerprints/AcknowledgementsLabelBuilderFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/utils/settings/fingerprints/AcknowledgementsLabelBuilderFingerprint.kt @@ -3,7 +3,7 @@ package app.revanced.patches.reddit.utils.settings.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch.LabelAcknowledgements -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object AcknowledgementsLabelBuilderFingerprint : MethodFingerprint( @@ -12,6 +12,6 @@ internal object AcknowledgementsLabelBuilderFingerprint : MethodFingerprint( parameters = listOf("Landroidx/preference/Preference;"), customFingerprint = { methodDef, _ -> methodDef.definingClass.startsWith("Lcom/reddit/screen/settings/preferences/") - && methodDef.containsWideLiteralInstructionIndex(LabelAcknowledgements) + && methodDef.containsWideLiteralInstructionValue(LabelAcknowledgements) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/shared/ads/BaseAdsPatch.kt b/src/main/kotlin/app/revanced/patches/shared/ads/BaseAdsPatch.kt index 90e3f1a80..931751c76 100644 --- a/src/main/kotlin/app/revanced/patches/shared/ads/BaseAdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/ads/BaseAdsPatch.kt @@ -14,8 +14,8 @@ import app.revanced.patches.shared.ads.fingerprints.VideoAdsFingerprint import app.revanced.patches.shared.integrations.Constants.PATCHES_PATH import app.revanced.util.getReference import app.revanced.util.getWalkerMethod -import app.revanced.util.getWideLiteralInstructionIndex import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @@ -41,8 +41,7 @@ abstract class BaseAdsPatch( MusicAdsFingerprint.resultOrThrow().let { it.mutableMethod.apply { val targetIndex = indexOfFirstInstructionOrThrow { - val reference = ((this as? ReferenceInstruction)?.reference as? MethodReference) - + val reference = getReference() opcode == Opcode.INVOKE_VIRTUAL && reference?.returnType == "V" && reference.parameterTypes.size == 1 @@ -75,7 +74,7 @@ abstract class BaseAdsPatch( internal fun MethodFingerprintResult.hookNonLithoFullscreenAds(literal: Long) { mutableMethod.apply { - val targetIndex = getWideLiteralInstructionIndex(literal) + 2 + val targetIndex = indexOfFirstWideLiteralInstructionValueOrThrow(literal) + 2 val targetRegister = getInstruction(targetIndex).registerA addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/shared/customspeed/BaseCustomPlaybackSpeedPatch.kt b/src/main/kotlin/app/revanced/patches/shared/customspeed/BaseCustomPlaybackSpeedPatch.kt index ca1e9b1de..b2e29869b 100644 --- a/src/main/kotlin/app/revanced/patches/shared/customspeed/BaseCustomPlaybackSpeedPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/customspeed/BaseCustomPlaybackSpeedPatch.kt @@ -8,14 +8,14 @@ import app.revanced.patcher.patch.BytecodePatch import app.revanced.patches.shared.customspeed.fingerprints.SpeedArrayGeneratorFingerprint import app.revanced.patches.shared.customspeed.fingerprints.SpeedLimiterFallBackFingerprint import app.revanced.patches.shared.customspeed.fingerprints.SpeedLimiterFingerprint -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithFieldReferenceTypeOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference abstract class BaseCustomPlaybackSpeedPatch( private val descriptor: String, @@ -39,7 +39,9 @@ abstract class BaseCustomPlaybackSpeedPatch( """ ) - val sizeIndex = getTargetIndexWithMethodReferenceNameOrThrow("size") + 1 + val sizeIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "size" + } + 1 val sizeRegister = getInstruction(sizeIndex).registerA addInstructions( @@ -49,7 +51,9 @@ abstract class BaseCustomPlaybackSpeedPatch( """ ) - val arrayIndex = getTargetIndexWithFieldReferenceTypeOrThrow("[F") + val arrayIndex = indexOfFirstInstructionOrThrow { + getReference()?.type == "[F" + } val arrayRegister = getInstruction(arrayIndex).registerA addInstructions( @@ -73,7 +77,7 @@ abstract class BaseCustomPlaybackSpeedPatch( val limiterMinConstIndex = indexOfFirstInstructionOrThrow { (this as? NarrowLiteralInstruction)?.narrowLiteral == 0.25f.toRawBits() } val limiterMaxConstIndex = - getTargetIndexOrThrow(limiterMinConstIndex + 1, Opcode.CONST_HIGH16) + indexOfFirstInstructionOrThrow(limiterMinConstIndex + 1, Opcode.CONST_HIGH16) val limiterMinConstDestination = getInstruction(limiterMinConstIndex).registerA diff --git a/src/main/kotlin/app/revanced/patches/shared/dialog/BaseViewerDiscretionDialogPatch.kt b/src/main/kotlin/app/revanced/patches/shared/dialog/BaseViewerDiscretionDialogPatch.kt index 93473d2ba..79000567e 100644 --- a/src/main/kotlin/app/revanced/patches/shared/dialog/BaseViewerDiscretionDialogPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/dialog/BaseViewerDiscretionDialogPatch.kt @@ -7,10 +7,12 @@ import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.shared.dialog.fingerprints.CreateDialogFingerprint -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.getReference import app.revanced.util.getWalkerMethod +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference abstract class BaseViewerDiscretionDialogPatch( private val classDescriptor: String, @@ -22,7 +24,9 @@ abstract class BaseViewerDiscretionDialogPatch( } ) { private fun MutableMethod.invoke(isAgeVerified: Boolean) { - val showDialogIndex = getTargetIndexWithMethodReferenceNameOrThrow("show") + val showDialogIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "show" + } val dialogRegister = getInstruction(showDialogIndex).registerC val methodName = diff --git a/src/main/kotlin/app/revanced/patches/shared/drawable/DrawableColorPatch.kt b/src/main/kotlin/app/revanced/patches/shared/drawable/DrawableColorPatch.kt index cf7ee092d..c0c53cf1e 100644 --- a/src/main/kotlin/app/revanced/patches/shared/drawable/DrawableColorPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/drawable/DrawableColorPatch.kt @@ -6,9 +6,11 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.shared.drawable.fingerprints.DrawableFingerprint -import app.revanced.util.getTargetIndexWithMethodReferenceNameReversedOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference object DrawableColorPatch : BytecodePatch( setOf(DrawableFingerprint) @@ -17,26 +19,26 @@ object DrawableColorPatch : BytecodePatch( DrawableFingerprint.resultOrThrow().mutableMethod.apply { insertMethod = this - insertIndex = getTargetIndexWithMethodReferenceNameReversedOrThrow("setColor") + insertIndex = indexOfFirstInstructionReversedOrThrow { + getReference()?.name == "setColor" + } insertRegister = getInstruction(insertIndex).registerD } } - private var offset = 0 - + private lateinit var insertMethod: MutableMethod private var insertIndex: Int = 0 private var insertRegister: Int = 0 - private lateinit var insertMethod: MutableMethod - + private var offset = 0 fun injectCall( methodDescriptor: String ) { insertMethod.addInstructions( insertIndex + offset, """ - invoke-static {v$insertRegister}, $methodDescriptor - move-result v$insertRegister - """ + invoke-static {v$insertRegister}, $methodDescriptor + move-result v$insertRegister + """ ) offset += 2 } diff --git a/src/main/kotlin/app/revanced/patches/shared/fingerprints/StartVideoInformerFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/fingerprints/StartVideoInformerFingerprint.kt index dec566143..ca8d33f53 100644 --- a/src/main/kotlin/app/revanced/patches/shared/fingerprints/StartVideoInformerFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/shared/fingerprints/StartVideoInformerFingerprint.kt @@ -12,5 +12,17 @@ internal object StartVideoInformerFingerprint : MethodFingerprint( Opcode.INVOKE_INTERFACE, Opcode.RETURN_VOID ), - strings = listOf("pc") + strings = listOf("pc"), + customFingerprint = custom@{ methodDef, _ -> + if (methodDef.implementation == null) + return@custom false + + methodDef.implementation!!.instructions + .withIndex() + .filter { (_, instruction) -> + instruction.opcode == Opcode.CONST_STRING + } + .map { (index, _) -> index } + .size == 1 + } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/VideoLengthFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/fingerprints/VideoLengthFingerprint.kt similarity index 84% rename from src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/VideoLengthFingerprint.kt rename to src/main/kotlin/app/revanced/patches/shared/fingerprints/VideoLengthFingerprint.kt index 34b4eb74a..bd916f6a6 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/VideoLengthFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/shared/fingerprints/VideoLengthFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.youtube.video.information.fingerprints +package app.revanced.patches.shared.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportPatch.kt b/src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportPatch.kt index 082c25e90..542b491e0 100644 --- a/src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportPatch.kt @@ -18,14 +18,12 @@ import app.revanced.patches.shared.gms.fingerprints.CastContextFetchFingerprint import app.revanced.patches.shared.gms.fingerprints.CastDynamiteModuleFingerprint import app.revanced.patches.shared.gms.fingerprints.CastDynamiteModuleV2Fingerprint import app.revanced.patches.shared.gms.fingerprints.CertificateFingerprint -import app.revanced.patches.shared.gms.fingerprints.CertificateFingerprint.GET_PACKAGE_NAME_METHOD_REFERENCE import app.revanced.patches.shared.gms.fingerprints.GmsCoreSupportFingerprint import app.revanced.patches.shared.gms.fingerprints.GooglePlayUtilityFingerprint import app.revanced.patches.shared.gms.fingerprints.PrimeMethodFingerprint import app.revanced.patches.shared.gms.fingerprints.ServiceCheckFingerprint import app.revanced.patches.shared.integrations.Constants.PATCHES_PATH import app.revanced.util.getReference -import app.revanced.util.getTargetIndexWithReference import app.revanced.util.resultOrThrow import app.revanced.util.returnEarly import com.android.tools.smali.dexlib2.Opcode @@ -178,7 +176,7 @@ abstract class BaseGmsCoreSupportPatch( CertificateFingerprint.result?.mutableClass?.methods?.forEach { mutableMethod -> mutableMethod.apply { val getPackageNameIndex = - getTargetIndexWithReference(GET_PACKAGE_NAME_METHOD_REFERENCE) + CertificateFingerprint.indexOfGetPackageNameInstruction(this) if (getPackageNameIndex > -1) { val targetRegister = diff --git a/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CertificateFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CertificateFingerprint.kt index 0632e3b1f..29d08c178 100644 --- a/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CertificateFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CertificateFingerprint.kt @@ -1,20 +1,28 @@ package app.revanced.patches.shared.gms.fingerprints import app.revanced.patcher.extensions.or -import app.revanced.patches.shared.gms.fingerprints.CertificateFingerprint.GET_PACKAGE_NAME_METHOD_REFERENCE -import app.revanced.util.fingerprint.ReferenceFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.shared.gms.fingerprints.CertificateFingerprint.indexOfGetPackageNameInstruction +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.MethodReference /** * Method which the package name is used to check the app signature. */ -internal object CertificateFingerprint : ReferenceFingerprint( +internal object CertificateFingerprint : MethodFingerprint( returnType = "Ljava/lang/String;", accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL, parameters = emptyList(), strings = listOf("X.509", "user", "S"), - reference = { GET_PACKAGE_NAME_METHOD_REFERENCE } + customFingerprint = { methodDef, _ -> + indexOfGetPackageNameInstruction(methodDef) >= 0 + } ) { - const val GET_PACKAGE_NAME_METHOD_REFERENCE = - "Landroid/content/Context;->getPackageName()Ljava/lang/String;" + fun indexOfGetPackageNameInstruction(methodDef: Method) = + methodDef.indexOfFirstInstruction { + getReference()?.toString() == "Landroid/content/Context;->getPackageName()Ljava/lang/String;" + } } diff --git a/src/main/kotlin/app/revanced/patches/shared/integrations/BaseIntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/shared/integrations/BaseIntegrationsPatch.kt index 3a33da4e9..4821a5108 100644 --- a/src/main/kotlin/app/revanced/patches/shared/integrations/BaseIntegrationsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/integrations/BaseIntegrationsPatch.kt @@ -4,10 +4,11 @@ import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException import app.revanced.patches.shared.integrations.BaseIntegrationsPatch.IntegrationsFingerprint.IRegisterResolver import app.revanced.patches.shared.integrations.Constants.INTEGRATIONS_UTILS_CLASS_DESCRIPTOR -import app.revanced.util.resultOrThrow +import app.revanced.util.exception +import app.revanced.util.findMethodOrThrow +import app.revanced.util.isDeprecated import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.ClassDef import com.android.tools.smali.dexlib2.iface.Method @@ -17,11 +18,7 @@ abstract class BaseIntegrationsPatch( ) : BytecodePatch(hooks) { override fun execute(context: BytecodeContext) { - if (context.findClass(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR) == null) { - throw PatchException( - "Integrations have not been merged yet. This patch can not succeed without merging the integrations.", - ) - } + context.findMethodOrThrow(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR) hooks.forEach { hook -> hook.invoke(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR) @@ -53,16 +50,21 @@ abstract class BaseIntegrationsPatch( ) { fun invoke(integrationsDescriptor: String) { - resultOrThrow().mutableMethod.let { method -> - val insertIndex = insertIndexResolver(method) - val contextRegister = contextRegisterResolver(method) + val method = result?.mutableMethod + ?: if (!isDeprecated()) { + throw exception + } else { + return + } - method.addInstruction( - insertIndex, - "invoke-static/range { $contextRegister .. $contextRegister }, " + - "$integrationsDescriptor->setContext(Landroid/content/Context;)V", - ) - } + val insertIndex = insertIndexResolver(method) + val contextRegister = contextRegisterResolver(method) + + method.addInstruction( + insertIndex, + "invoke-static/range { $contextRegister .. $contextRegister }, " + + "$integrationsDescriptor->setContext(Landroid/content/Context;)V", + ) } interface IHookInsertIndexResolver : (Method) -> Int { diff --git a/src/main/kotlin/app/revanced/patches/shared/litho/LithoFilterPatch.kt b/src/main/kotlin/app/revanced/patches/shared/litho/LithoFilterPatch.kt index 545556945..5f3092409 100644 --- a/src/main/kotlin/app/revanced/patches/shared/litho/LithoFilterPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/litho/LithoFilterPatch.kt @@ -7,7 +7,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.or import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.util.smali.ExternalLabel @@ -15,10 +14,11 @@ import app.revanced.patches.shared.integrations.Constants.COMPONENTS_PATH import app.revanced.patches.shared.litho.fingerprints.ByteBufferFingerprint import app.revanced.patches.shared.litho.fingerprints.EmptyComponentsFingerprint import app.revanced.patches.shared.litho.fingerprints.PathBuilderFingerprint +import app.revanced.util.findMethodsOrThrow import app.revanced.util.getReference -import app.revanced.util.getStringInstructionIndex import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode @@ -127,7 +127,7 @@ object LithoFilterPatch : BytecodePatch( val stringBuilderRegister = getInstruction(stringBuilderIndex).registerA - val emptyStringIndex = getStringInstructionIndex("") + val emptyStringIndex = indexOfFirstStringInstructionOrThrow("") val identifierRegister = getInstruction( indexOfFirstInstructionReversedOrThrow(emptyStringIndex) { opcode == Opcode.IPUT_OBJECT @@ -156,10 +156,8 @@ object LithoFilterPatch : BytecodePatch( // Create a new method to get the filter array to avoid register conflicts. // This fixes an issue with Integrations compiled with Android Gradle Plugin 8.3.0+. // https://github.com/ReVanced/revanced-patches/issues/2818 - val lithoFilterMethods = context.findClass(INTEGRATIONS_LITHO_FILER_CLASS_DESCRIPTOR) - ?.mutableClass - ?.methods - ?: throw PatchException("LithoFilterPatch class not found.") + val lithoFilterMethods = + context.findMethodsOrThrow(INTEGRATIONS_LITHO_FILER_CLASS_DESCRIPTOR) lithoFilterMethods .first { it.name == "" } diff --git a/src/main/kotlin/app/revanced/patches/shared/mainactivity/BaseMainActivityResolvePatch.kt b/src/main/kotlin/app/revanced/patches/shared/mainactivity/BaseMainActivityResolvePatch.kt index 02e3c8135..e34e5d56f 100644 --- a/src/main/kotlin/app/revanced/patches/shared/mainactivity/BaseMainActivityResolvePatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/mainactivity/BaseMainActivityResolvePatch.kt @@ -7,7 +7,7 @@ import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchException import app.revanced.patcher.util.proxy.mutableTypes.MutableClass import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.util.getTargetIndexOrThrow +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import kotlin.properties.Delegates @@ -38,7 +38,8 @@ abstract class BaseMainActivityResolvePatch( // set onBackPressed method onBackPressedMethod = getMethod("onBackPressed") - onBackPressedMethodIndex = onBackPressedMethod.getTargetIndexOrThrow(Opcode.RETURN_VOID) + onBackPressedMethodIndex = + onBackPressedMethod.indexOfFirstInstructionOrThrow(Opcode.RETURN_VOID) // set onConfigurationChanged method onConfigurationChangedMethod = getMethod("onConfigurationChanged") diff --git a/src/main/kotlin/app/revanced/patches/shared/opus/BaseOpusCodecsPatch.kt b/src/main/kotlin/app/revanced/patches/shared/opus/BaseOpusCodecsPatch.kt index 6a8984cf2..8344971ad 100644 --- a/src/main/kotlin/app/revanced/patches/shared/opus/BaseOpusCodecsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/opus/BaseOpusCodecsPatch.kt @@ -7,11 +7,13 @@ import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.shared.opus.fingerprints.CodecReferenceFingerprint import app.revanced.patches.shared.opus.fingerprints.CodecSelectorFingerprint -import app.revanced.util.getTargetIndexWithReferenceOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction -import com.android.tools.smali.dexlib2.iface.reference.Reference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference /** * This patch is generally not required for the latest versions of YouTube and YouTube Music. @@ -25,15 +27,14 @@ abstract class BaseOpusCodecsPatch( CodecSelectorFingerprint ) ) { - private lateinit var opusCodecReference: Reference - override fun execute(context: BytecodeContext) { - CodecReferenceFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - val targetIndex = getTargetIndexWithReferenceOrThrow("Ljava/util/Set;") - opusCodecReference = getInstruction(targetIndex).reference + val opusCodecReference = with(CodecReferenceFingerprint.resultOrThrow().mutableMethod) { + val codecIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_STATIC && + getReference()?.returnType == "Ljava/util/Set;" } + getInstruction(codecIndex).reference } CodecSelectorFingerprint.resultOrThrow().let { diff --git a/src/main/kotlin/app/revanced/patches/shared/settingmenu/SettingsMenuPatch.kt b/src/main/kotlin/app/revanced/patches/shared/settingmenu/SettingsMenuPatch.kt index 3ed3ba57c..d6a487dfb 100644 --- a/src/main/kotlin/app/revanced/patches/shared/settingmenu/SettingsMenuPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/settingmenu/SettingsMenuPatch.kt @@ -8,9 +8,11 @@ import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.shared.integrations.Constants.PATCHES_PATH import app.revanced.patches.shared.settingmenu.fingerprints.SettingsMenuFingerprint import app.revanced.patches.shared.viewgroup.ViewGroupMarginLayoutParamsHookPatch -import app.revanced.util.getTargetIndexWithFieldReferenceTypeOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference @Patch( description = "Hide the settings menu for YouTube or YouTube Music.", @@ -25,8 +27,9 @@ object SettingsMenuPatch : BytecodePatch( override fun execute(context: BytecodeContext) { SettingsMenuFingerprint.resultOrThrow().mutableMethod.apply { - val insertIndex = - getTargetIndexWithFieldReferenceTypeOrThrow("Landroid/support/v7/widget/RecyclerView;") + val insertIndex = indexOfFirstInstructionOrThrow { + getReference()?.type == "Landroid/support/v7/widget/RecyclerView;" + } val insertRegister = getInstruction(insertIndex).registerA addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/shared/spoofappversion/BaseSpoofAppVersionPatch.kt b/src/main/kotlin/app/revanced/patches/shared/spoofappversion/BaseSpoofAppVersionPatch.kt index 9bcca0159..c8254ad5f 100644 --- a/src/main/kotlin/app/revanced/patches/shared/spoofappversion/BaseSpoofAppVersionPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/spoofappversion/BaseSpoofAppVersionPatch.kt @@ -6,7 +6,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patches.shared.fingerprints.CreatePlayerRequestBodyWithModelFingerprint import app.revanced.patches.shared.fingerprints.CreatePlayerRequestBodyWithModelFingerprint.indexOfReleaseInstruction -import app.revanced.util.getTargetIndexReversedOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction @@ -20,7 +20,8 @@ abstract class BaseSpoofAppVersionPatch( CreatePlayerRequestBodyWithModelFingerprint.resultOrThrow().mutableMethod.apply { val versionIndex = indexOfReleaseInstruction(this) + 1 - val insertIndex = getTargetIndexReversedOrThrow(versionIndex, Opcode.IPUT_OBJECT) + val insertIndex = + indexOfFirstInstructionReversedOrThrow(versionIndex, Opcode.IPUT_OBJECT) val insertRegister = getInstruction(insertIndex).registerA addInstructions( diff --git a/src/main/kotlin/app/revanced/patches/shared/viewgroup/ViewGroupMarginLayoutParamsHookPatch.kt b/src/main/kotlin/app/revanced/patches/shared/viewgroup/ViewGroupMarginLayoutParamsHookPatch.kt index 3dfe48d4c..b504a8a7f 100644 --- a/src/main/kotlin/app/revanced/patches/shared/viewgroup/ViewGroupMarginLayoutParamsHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/viewgroup/ViewGroupMarginLayoutParamsHookPatch.kt @@ -3,12 +3,12 @@ package app.revanced.patches.shared.viewgroup import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.shared.integrations.Constants.INTEGRATIONS_UTILS_CLASS_DESCRIPTOR import app.revanced.patches.shared.viewgroup.fingerprints.ViewGroupMarginFingerprint import app.revanced.patches.shared.viewgroup.fingerprints.ViewGroupMarginParentFingerprint -import app.revanced.util.resultOrThrow +import app.revanced.util.alsoResolve +import app.revanced.util.findMethodOrThrow @Patch( description = "Hook YouTube or YouTube Music to use ViewGroup.MarginLayoutParams in the integration.", @@ -18,26 +18,21 @@ object ViewGroupMarginLayoutParamsHookPatch : BytecodePatch( ) { override fun execute(context: BytecodeContext) { - val method = - context.findClass(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR)?.mutableClass?.methods?.first { method -> - method.name == "hideViewGroupByMarginLayoutParams" - } ?: throw PatchException("Could not find hideViewGroupByMarginLayoutParams method") + val setViewGroupMarginCall = with( + ViewGroupMarginFingerprint.alsoResolve( + context, ViewGroupMarginParentFingerprint + ).mutableMethod + ) { + "$definingClass->$name(Landroid/view/View;II)V" + } - ViewGroupMarginFingerprint.resolve( - context, - ViewGroupMarginParentFingerprint.resultOrThrow().classDef + context.findMethodOrThrow(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR) { + name == "hideViewGroupByMarginLayoutParams" + }.addInstructions( + 0, """ + const/4 v0, 0x0 + invoke-static {p0, v0, v0}, $setViewGroupMarginCall + """ ) - ViewGroupMarginFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - val setViewGroupMarginCall = "$definingClass->$name(Landroid/view/View;II)V" - - method.addInstructions( - 0, """ - const/4 v0, 0x0 - invoke-static {p0, v0, v0}, $setViewGroupMarginCall - """ - ) - } - } } } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/ads/general/fingerprints/ShowDialogCommandFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/ads/general/fingerprints/ShowDialogCommandFingerprint.kt index 1edafb0b1..e747815bf 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/ads/general/fingerprints/ShowDialogCommandFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/ads/general/fingerprints/ShowDialogCommandFingerprint.kt @@ -2,7 +2,7 @@ package app.revanced.patches.youtube.ads.general.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.SlidingDialogAnimation -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.Opcode internal object ShowDialogCommandFingerprint : MethodFingerprint( @@ -16,7 +16,7 @@ internal object ShowDialogCommandFingerprint : MethodFingerprint( // 18.43 and earlier has a different first parameter. // Since this fingerprint is somewhat weak, work around by checking for both method parameter signatures. customFingerprint = custom@{ methodDef, _ -> - if (!methodDef.containsWideLiteralInstructionIndex(SlidingDialogAnimation)) { + if (!methodDef.containsWideLiteralInstructionValue(SlidingDialogAnimation)) { return@custom false } // 18.43 and earlier parameters are: "L", "L" diff --git a/src/main/kotlin/app/revanced/patches/youtube/feed/components/FeedComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/feed/components/FeedComponentsPatch.kt index 0e513c8f7..1ed6fc011 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/feed/components/FeedComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/feed/components/FeedComponentsPatch.kt @@ -7,6 +7,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.patch.PatchException +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.shared.litho.LithoFilterPatch import app.revanced.patches.youtube.feed.components.fingerprints.BreakingNewsFingerprint @@ -19,33 +20,42 @@ import app.revanced.patches.youtube.feed.components.fingerprints.ChannelTabBuild import app.revanced.patches.youtube.feed.components.fingerprints.ChannelTabRendererFingerprint import app.revanced.patches.youtube.feed.components.fingerprints.ElementParserFingerprint import app.revanced.patches.youtube.feed.components.fingerprints.ElementParserParentFingerprint +import app.revanced.patches.youtube.feed.components.fingerprints.EngagementPanelUpdateFingerprint import app.revanced.patches.youtube.feed.components.fingerprints.FilterBarHeightFingerprint import app.revanced.patches.youtube.feed.components.fingerprints.LatestVideosButtonFingerprint +import app.revanced.patches.youtube.feed.components.fingerprints.LinearLayoutManagerItemCountsFingerprint import app.revanced.patches.youtube.feed.components.fingerprints.RelatedChipCloudFingerprint import app.revanced.patches.youtube.feed.components.fingerprints.SearchResultsChipBarFingerprint import app.revanced.patches.youtube.feed.components.fingerprints.ShowMoreButtonFingerprint +import app.revanced.patches.youtube.utils.bottomsheet.BottomSheetHookPatch import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE +import app.revanced.patches.youtube.utils.fingerprints.EngagementPanelBuilderFingerprint import app.revanced.patches.youtube.utils.fingerprints.ScrollTopParentFingerprint import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH import app.revanced.patches.youtube.utils.integrations.Constants.FEED_CLASS_DESCRIPTOR +import app.revanced.patches.youtube.utils.integrations.Constants.FEED_PATH import app.revanced.patches.youtube.utils.navigation.NavigationBarHookPatch import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.CaptionToggleContainer import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceName -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.alsoResolve +import app.revanced.util.getReference +import app.revanced.util.getWalkerMethod +import app.revanced.util.indexOfFirstInstruction import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode +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.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference +import com.android.tools.smali.dexlib2.util.MethodUtil @Suppress("unused") object FeedComponentsPatch : BaseBytecodePatch( @@ -56,7 +66,8 @@ object FeedComponentsPatch : BaseBytecodePatch( NavigationBarHookPatch::class, PlayerTypeHookPatch::class, SettingsPatch::class, - SharedResourceIdPatch::class + SharedResourceIdPatch::class, + BottomSheetHookPatch::class, ), compatiblePackages = COMPATIBLE_PACKAGE, fingerprints = setOf( @@ -68,14 +79,18 @@ object FeedComponentsPatch : BaseBytecodePatch( ChannelListSubMenuTabletSyntheticFingerprint, ChannelTabRendererFingerprint, ElementParserParentFingerprint, + EngagementPanelBuilderFingerprint, FilterBarHeightFingerprint, LatestVideosButtonFingerprint, + LinearLayoutManagerItemCountsFingerprint, RelatedChipCloudFingerprint, ScrollTopParentFingerprint, SearchResultsChipBarFingerprint, - ShowMoreButtonFingerprint + ShowMoreButtonFingerprint, ) ) { + private const val CAROUSEL_SHELF_FILTER_CLASS_DESCRIPTOR = + "$COMPONENTS_PATH/CarouselShelfFilter;" private const val FEED_COMPONENTS_FILTER_CLASS_DESCRIPTOR = "$COMPONENTS_PATH/FeedComponentsFilter;" private const val FEED_VIDEO_FILTER_CLASS_DESCRIPTOR = @@ -84,6 +99,8 @@ object FeedComponentsPatch : BaseBytecodePatch( "$COMPONENTS_PATH/FeedVideoViewsFilter;" private const val KEYWORD_FILTER_CLASS_DESCRIPTOR = "$COMPONENTS_PATH/KeywordContentFilter;" + private const val RELATED_VIDEO_CLASS_DESCRIPTOR = + "$FEED_PATH/RelatedVideoPatch;" override fun execute(context: BytecodeContext) { @@ -113,8 +130,8 @@ object FeedComponentsPatch : BaseBytecodePatch( // region patch for hide caption button CaptionsButtonFingerprint.resultOrThrow().mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(CaptionToggleContainer) - val insertIndex = getTargetIndexReversedOrThrow(constIndex, Opcode.IF_EQZ) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(CaptionToggleContainer) + val insertIndex = indexOfFirstInstructionReversedOrThrow(constIndex, Opcode.IF_EQZ) val insertRegister = getInstruction(insertIndex).registerA addInstructions( @@ -126,8 +143,8 @@ object FeedComponentsPatch : BaseBytecodePatch( } CaptionsButtonSyntheticFingerprint.resultOrThrow().mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(CaptionToggleContainer) - val targetIndex = getTargetIndexOrThrow(constIndex, Opcode.MOVE_RESULT_OBJECT) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(CaptionToggleContainer) + val targetIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.MOVE_RESULT_OBJECT) val targetRegister = getInstruction(targetIndex).registerA addInstruction( @@ -138,6 +155,62 @@ object FeedComponentsPatch : BaseBytecodePatch( // endregion + // region patch for hide relative video + + fun Method.indexOfEngagementPanelBuilderInstruction(targetMethod: MutableMethod) = + indexOfFirstInstruction { + opcode == Opcode.INVOKE_DIRECT && + MethodUtil.methodSignaturesMatch( + targetMethod, + getReference()!! + ) + } + + EngagementPanelBuilderFingerprint.resultOrThrow().let { + it.mutableClass.methods.filter { method -> + method.indexOfEngagementPanelBuilderInstruction(it.mutableMethod) >= 0 + }.forEach { method -> + method.apply { + val index = indexOfEngagementPanelBuilderInstruction(it.mutableMethod) + val register = getInstruction(index + 1).registerA + + addInstruction( + index + 2, + "invoke-static {v$register}, " + + "$RELATED_VIDEO_CLASS_DESCRIPTOR->showEngagementPanel(Ljava/lang/Object;)V" + ) + } + } + } + + EngagementPanelUpdateFingerprint.alsoResolve( + context, EngagementPanelBuilderFingerprint + ).mutableMethod.addInstruction( + 0, + "invoke-static {}, $RELATED_VIDEO_CLASS_DESCRIPTOR->hideEngagementPanel()V" + ) + + // BytecodeUtils.getWalkerMethod must be used here + // Otherwise, MethodWalker finds the wrong class in YouTube 18.29.38: + // https://github.com/ReVanced/revanced-patcher/issues/309 + LinearLayoutManagerItemCountsFingerprint.resultOrThrow().let { + val methodWalker = + it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex) + methodWalker.apply { + val index = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT) + val register = getInstruction(index).registerA + + addInstructions( + index + 1, """ + invoke-static {v$register}, $RELATED_VIDEO_CLASS_DESCRIPTOR->overrideItemCounts(I)I + move-result v$register + """ + ) + } + } + + // endregion + // region patch for hide subscriptions channel section for tablet arrayOf( @@ -198,7 +271,7 @@ object FeedComponentsPatch : BaseBytecodePatch( && reference.returnType.startsWith("L") } - val objectIndex = getTargetIndexOrThrow(Opcode.MOVE_OBJECT) + val objectIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_OBJECT) val objectRegister = getInstruction(objectIndex).registerA val jumpIndex = it.scanResult.patternScanResult!!.startIndex @@ -253,7 +326,9 @@ object FeedComponentsPatch : BaseBytecodePatch( ChannelTabRendererFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val iteratorIndex = getTargetIndexWithMethodReferenceName("hasNext") + val iteratorIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "hasNext" + } val iteratorRegister = getInstruction(iteratorIndex).registerC @@ -265,7 +340,8 @@ object FeedComponentsPatch : BaseBytecodePatch( && reference.parameterTypes == channelTabBuilderMethod.parameterTypes } - val objectIndex = getTargetIndexReversedOrThrow(targetIndex, Opcode.IGET_OBJECT) + val objectIndex = + indexOfFirstInstructionReversedOrThrow(targetIndex, Opcode.IGET_OBJECT) val objectInstruction = getInstruction(objectIndex) val objectReference = getInstruction(objectIndex).reference @@ -285,6 +361,7 @@ object FeedComponentsPatch : BaseBytecodePatch( // endregion + LithoFilterPatch.addFilter(CAROUSEL_SHELF_FILTER_CLASS_DESCRIPTOR) LithoFilterPatch.addFilter(FEED_COMPONENTS_FILTER_CLASS_DESCRIPTOR) LithoFilterPatch.addFilter(FEED_VIDEO_FILTER_CLASS_DESCRIPTOR) LithoFilterPatch.addFilter(FEED_VIDEO_VIEWS_FILTER_CLASS_DESCRIPTOR) diff --git a/src/main/kotlin/app/revanced/patches/youtube/feed/components/fingerprints/EngagementPanelUpdateFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/feed/components/fingerprints/EngagementPanelUpdateFingerprint.kt new file mode 100644 index 000000000..4d378d659 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/feed/components/fingerprints/EngagementPanelUpdateFingerprint.kt @@ -0,0 +1,21 @@ +package app.revanced.patches.youtube.feed.components.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.reference.MethodReference + +internal object EngagementPanelUpdateFingerprint : MethodFingerprint( + returnType = "V", + accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL, + parameters = listOf("L", "Z"), + customFingerprint = { methodDef, _ -> + methodDef.indexOfFirstInstruction { + opcode == Opcode.INVOKE_VIRTUAL && + getReference().toString() == "Ljava/util/ArrayDeque;->pop()Ljava/lang/Object;" + } >= 0 + } +) diff --git a/src/main/kotlin/app/revanced/patches/youtube/feed/components/fingerprints/LinearLayoutManagerItemCountsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/feed/components/fingerprints/LinearLayoutManagerItemCountsFingerprint.kt new file mode 100644 index 000000000..0a4dc4688 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/feed/components/fingerprints/LinearLayoutManagerItemCountsFingerprint.kt @@ -0,0 +1,19 @@ +package app.revanced.patches.youtube.feed.components.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +internal object LinearLayoutManagerItemCountsFingerprint : MethodFingerprint( + returnType = "I", + accessFlags = AccessFlags.FINAL.value, + parameters = listOf("L", "L", "L", "Z"), + opcodes = listOf( + Opcode.IF_NEZ, + Opcode.IF_LEZ, + Opcode.INVOKE_VIRTUAL, + ), + customFingerprint = { methodDef, _ -> + methodDef.definingClass == "Landroid/support/v7/widget/LinearLayoutManager;" + } +) diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/audiotracks/AudioTracksPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/audiotracks/AudioTracksPatch.kt index bfa0c5270..a5a087b43 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/audiotracks/AudioTracksPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/audiotracks/AudioTracksPatch.kt @@ -7,7 +7,7 @@ import app.revanced.patches.youtube.general.audiotracks.fingerprints.StreamingMo import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexWithReferenceOrThrow +import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow @@ -15,6 +15,7 @@ import com.android.tools.smali.dexlib2.Opcode 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.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Suppress("unused") object AudioTracksPatch : BaseBytecodePatch( @@ -32,15 +33,14 @@ object AudioTracksPatch : BaseBytecodePatch( opcode == Opcode.CHECK_CAST && (this as ReferenceInstruction).reference.toString() == "Lcom/google/android/libraries/youtube/innertube/model/media/FormatStreamModel;" } - val arrayListIndex = getTargetIndexWithReferenceOrThrow( - formatStreamModelIndex, - "Ljava/util/List;->add(Ljava/lang/Object;)Z" - ) - val insertIndex = - getTargetIndexWithReferenceOrThrow( - arrayListIndex, - "Ljava/util/List;->isEmpty()Z" - ) + 2 + val arrayListIndex = indexOfFirstInstructionOrThrow(formatStreamModelIndex) { + opcode == Opcode.INVOKE_INTERFACE && + getReference()?.toString() == "Ljava/util/List;->add(Ljava/lang/Object;)Z" + } + val insertIndex = indexOfFirstInstructionOrThrow(arrayListIndex) { + opcode == Opcode.INVOKE_INTERFACE && + getReference()?.toString() == "Ljava/util/List;->isEmpty()Z" + } + 2 val formatStreamModelRegister = getInstruction(formatStreamModelIndex).registerA diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/components/LayoutComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/components/LayoutComponentsPatch.kt index 297c3a878..dded8f631 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/components/LayoutComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/components/LayoutComponentsPatch.kt @@ -27,9 +27,9 @@ import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_D import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.AccountSwitcherAccessibility import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceName -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -37,6 +37,7 @@ 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.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.util.MethodUtil @Suppress("unused") @@ -171,10 +172,13 @@ object LayoutComponentsPatch : BaseBytecodePatch( AccountSwitcherAccessibilityLabelFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(AccountSwitcherAccessibility) - val insertIndex = getTargetIndexOrThrow(constIndex, Opcode.IF_EQZ) - val setVisibilityIndex = - getTargetIndexWithMethodReferenceName(insertIndex, "setVisibility") + val constIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(AccountSwitcherAccessibility) + val insertIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.IF_EQZ) + val setVisibilityIndex = indexOfFirstInstructionOrThrow(insertIndex) { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setVisibility" + } val visibilityRegister = getInstruction(setVisibilityIndex).registerD @@ -209,8 +213,8 @@ object LayoutComponentsPatch : BaseBytecodePatch( // region patch for hide tooltip content TooltipContentFullscreenFingerprint.resultOrThrow().mutableMethod.apply { - val literalIndex = getWideLiteralInstructionIndex(45384061) - val targetIndex = getTargetIndexOrThrow(literalIndex, Opcode.MOVE_RESULT) + val literalIndex = indexOfFirstWideLiteralInstructionValueOrThrow(45384061) + val targetIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT) val targetRegister = getInstruction(targetIndex).registerA addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/downloads/DownloadActionsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/downloads/DownloadActionsPatch.kt index f1fe0d3f1..688d34454 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/downloads/DownloadActionsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/downloads/DownloadActionsPatch.kt @@ -19,6 +19,7 @@ import app.revanced.patches.youtube.utils.pip.PiPStateHookPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.util.alsoResolve +import app.revanced.util.findMethodOrThrow import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch @@ -87,23 +88,22 @@ object DownloadActionsPatch : BaseBytecodePatch( ?: throw PatchException("Could not find onClickListenerClass") } - context.findClass(onClickListenerClass) - ?.mutableClass - ?.methods - ?.first { method -> method.name == "onClick" }?.apply { - val insertIndex = indexOfFirstInstructionOrThrow { - opcode == Opcode.INVOKE_STATIC - && getReference()?.name == "isEmpty" - } - val insertRegister = getInstruction(insertIndex).registerC + context.findMethodOrThrow(onClickListenerClass) { + name == "onClick" + }.apply { + val insertIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_STATIC + && getReference()?.name == "isEmpty" + } + val insertRegister = getInstruction(insertIndex).registerC - addInstructions( - insertIndex, """ - invoke-static {v$insertRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->inAppPlaylistDownloadButtonOnClick(Ljava/lang/String;)Ljava/lang/String; - move-result-object v$insertRegister - """ - ) - } ?: throw PatchException("Could not find class $onClickListenerClass") + addInstructions( + insertIndex, """ + invoke-static {v$insertRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->inAppPlaylistDownloadButtonOnClick(Ljava/lang/String;)Ljava/lang/String; + move-result-object v$insertRegister + """ + ) + } OfflinePlaylistEndpointFingerprint.resultOrThrow().mutableMethod.apply { val playlistIdParameter = parameterTypes.indexOf("Ljava/lang/String;") + 1 @@ -176,7 +176,7 @@ object DownloadActionsPatch : BaseBytecodePatch( SettingsPatch.addPreference( arrayOf( "PREFERENCE_SCREEN: GENERAL", - "PREFERENCE_CATEGORY: GENERAL_EXPERIMENTAL_FLAGS", + "SETTINGS: HOOK_BUTTONS", "SETTINGS: HOOK_DOWNLOAD_ACTIONS" ) ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/layoutswitch/LayoutSwitchPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/layoutswitch/LayoutSwitchPatch.kt index 9b38b5f04..f4c8c6139 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/layoutswitch/LayoutSwitchPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/layoutswitch/LayoutSwitchPatch.kt @@ -10,8 +10,7 @@ import app.revanced.patches.youtube.general.layoutswitch.fingerprints.LayoutSwit import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -34,7 +33,7 @@ object LayoutSwitchPatch : BaseBytecodePatch( GetFormFactorFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val jumpIndex = getTargetIndexReversedOrThrow(Opcode.SGET_OBJECT) + val jumpIndex = indexOfFirstInstructionReversedOrThrow(Opcode.SGET_OBJECT) addInstructionsWithLabels( 0, """ @@ -56,7 +55,7 @@ object LayoutSwitchPatch : BaseBytecodePatch( LayoutSwitchFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = getTargetIndexOrThrow(Opcode.IF_NEZ) + val insertIndex = indexOfFirstInstructionReversedOrThrow(Opcode.IF_NEZ) val insertRegister = getInstruction(insertIndex).registerA addInstructions( diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/loadingscreen/GradientLoadingScreenPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/loadingscreen/GradientLoadingScreenPatch.kt index b6d844a46..2bb8182cb 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/loadingscreen/GradientLoadingScreenPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/loadingscreen/GradientLoadingScreenPatch.kt @@ -6,7 +6,7 @@ import app.revanced.patches.youtube.general.loadingscreen.fingerprints.GradientL import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.patch.BaseBytecodePatch @Suppress("unused") @@ -29,7 +29,7 @@ object GradientLoadingScreenPatch : BaseBytecodePatch( GradientLoadingScreenPrimaryFingerprint to 45412406, GradientLoadingScreenSecondaryFingerprint to 45418917 ).forEach { (fingerprint, literal) -> - fingerprint.literalInstructionBooleanHook( + fingerprint.injectLiteralInstructionBooleanCall( literal, "$GENERAL_CLASS_DESCRIPTOR->enableGradientLoadingScreen()Z" ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/MiniplayerPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/MiniplayerPatch.kt index b5a2529db..8482e06f7 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/MiniplayerPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/MiniplayerPatch.kt @@ -44,8 +44,8 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint import app.revanced.util.getReference import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.indexOfWideLiteralInstructionOrThrow -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.AccessFlags @@ -170,7 +170,7 @@ object MiniplayerPatch : BaseBytecodePatch( } if (SettingsPatch.upward1925) { - MiniplayerModernEnabledFingerprint.literalInstructionBooleanHook( + MiniplayerModernEnabledFingerprint.injectLiteralInstructionBooleanCall( 45622882, "$INTEGRATIONS_CLASS_DESCRIPTOR->getModernMiniplayerOverride(Z)Z" ) @@ -181,11 +181,11 @@ object MiniplayerPatch : BaseBytecodePatch( // region Enable double tap action. if (SettingsPatch.upward1925) { - MiniplayerModernConstructorFingerprint.literalInstructionBooleanHook( + MiniplayerModernConstructorFingerprint.injectLiteralInstructionBooleanCall( 45628823, "$INTEGRATIONS_CLASS_DESCRIPTOR->enableMiniplayerDoubleTapAction()Z" ) - MiniplayerModernConstructorFingerprint.literalInstructionBooleanHook( + MiniplayerModernConstructorFingerprint.injectLiteralInstructionBooleanCall( 45630429, "$INTEGRATIONS_CLASS_DESCRIPTOR->getModernMiniplayerOverride(Z)Z" ) @@ -211,7 +211,8 @@ object MiniplayerPatch : BaseBytecodePatch( YtOutlinePictureInPictureWhite to YtOutlineXWhite, YtOutlineXWhite to YtOutlinePictureInPictureWhite, ).forEach { (originalResource, replacementResource) -> - val imageResourceIndex = indexOfWideLiteralInstructionOrThrow(originalResource) + val imageResourceIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(originalResource) val register = getInstruction(imageResourceIndex).registerA @@ -321,7 +322,7 @@ object MiniplayerPatch : BaseBytecodePatch( // region Enable drag and drop. if (SettingsPatch.upward1923) { - MiniplayerModernDragAndDropFingerprint.literalInstructionBooleanHook( + MiniplayerModernDragAndDropFingerprint.injectLiteralInstructionBooleanCall( 45628752, "$INTEGRATIONS_CLASS_DESCRIPTOR->enableMiniplayerDragAndDrop()Z" ) @@ -388,7 +389,7 @@ object MiniplayerPatch : BaseBytecodePatch( ) { resultOrThrow().mutableMethod.apply { val imageViewIndex = indexOfFirstInstructionOrThrow( - indexOfWideLiteralInstructionOrThrow(literalValue) + indexOfFirstWideLiteralInstructionValueOrThrow(literalValue) ) { opcode == Opcode.CHECK_CAST && getReference()?.type == hookedClassType } diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/fingerprints/MiniplayerModernConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/fingerprints/MiniplayerModernConstructorFingerprint.kt index 47b8480c3..eba01fd68 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/fingerprints/MiniplayerModernConstructorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/fingerprints/MiniplayerModernConstructorFingerprint.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.general.miniplayer.fingerprints.MiniplayerModernConstructorFingerprint.constructorMethodCount import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.util.MethodUtil @@ -13,7 +13,7 @@ internal object MiniplayerModernConstructorFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, parameters = listOf("L"), customFingerprint = custom@{ methodDef, classDef -> - if (!methodDef.containsWideLiteralInstructionIndex(45623000)) // Magic number found in the constructor. + if (!methodDef.containsWideLiteralInstructionValue(45623000)) // Magic number found in the constructor. return@custom false classDef.methods.forEach { @@ -24,8 +24,8 @@ internal object MiniplayerModernConstructorFingerprint : MethodFingerprint( return@custom true // Double tap action (Used in YouTube 19.25.39+). - methodDef.containsWideLiteralInstructionIndex(45628823) - && methodDef.containsWideLiteralInstructionIndex(45630429) + methodDef.containsWideLiteralInstructionValue(45628823) + && methodDef.containsWideLiteralInstructionValue(45630429) } ) { private var constructorMethodCount = 0 diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/music/YouTubeMusicActionsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/music/YouTubeMusicActionsPatch.kt new file mode 100644 index 000000000..9b49e8603 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/general/music/YouTubeMusicActionsPatch.kt @@ -0,0 +1,109 @@ +package app.revanced.patches.youtube.general.music + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction +import app.revanced.patches.youtube.general.music.fingerprints.AppDeepLinkFingerprint +import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE +import app.revanced.patches.youtube.utils.gms.GmsCoreSupportResourcePatch.PackageNameYouTubeMusic +import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_PATH +import app.revanced.patches.youtube.utils.settings.ResourceUtils.addEntryValues +import app.revanced.patches.youtube.utils.settings.SettingsBytecodePatch +import app.revanced.patches.youtube.utils.settings.SettingsPatch +import app.revanced.util.findMethodOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.patch.BaseBytecodePatch +import app.revanced.util.resultOrThrow +import app.revanced.util.valueOrThrow +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import java.io.Closeable + +@Suppress("unused") +object YouTubeMusicActionsPatch : BaseBytecodePatch( + name = "Hook YouTube Music actions", + description = "Adds support for opening music in RVX Music using the in-app YouTube Music button.", + dependencies = setOf(SettingsPatch::class), + compatiblePackages = COMPATIBLE_PACKAGE, + fingerprints = setOf(AppDeepLinkFingerprint) +), Closeable { + private const val INTEGRATIONS_CLASS_DESCRIPTOR = + "$GENERAL_PATH/YouTubeMusicActionsPatch;" + + override fun execute(context: BytecodeContext) { + + AppDeepLinkFingerprint.resultOrThrow().let { + it.mutableMethod.apply { + val packageNameIndex = it.scanResult.patternScanResult!!.startIndex + val packageNameField = + getInstruction(packageNameIndex).reference.toString() + + implementation!!.instructions + .withIndex() + .filter { (_, instruction) -> + instruction.opcode == Opcode.IGET_OBJECT && + instruction.getReference() + ?.toString() == packageNameField + } + .map { (index, _) -> index } + .reversed() + .forEach { index -> + val register = getInstruction(index).registerA + + addInstructions( + index + 1, """ + invoke-static {v$register}, $INTEGRATIONS_CLASS_DESCRIPTOR->overridePackageName(Ljava/lang/String;)Ljava/lang/String; + move-result-object v$register + """ + ) + } + } + } + + /** + * Add settings + */ + SettingsPatch.addPreference( + arrayOf( + "PREFERENCE_SCREEN: GENERAL", + "SETTINGS: HOOK_BUTTONS", + "SETTINGS: HOOK_YOUTUBE_MUSIC_ACTIONS" + ) + ) + + SettingsPatch.updatePatchStatus(this) + } + + override fun close() { + if (SettingsPatch.containsPatch("GmsCore support")) { + val musicPackageName = PackageNameYouTubeMusic.valueOrThrow() + SettingsPatch.contexts.addEntryValues( + "revanced_third_party_youtube_music_label", + "RVX Music" + ) + SettingsPatch.contexts.addEntryValues( + "revanced_third_party_youtube_music_package_name", + musicPackageName + ) + + SettingsBytecodePatch.contexts.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) { + name == "getRVXMusicPackageName" + }.apply { + val replaceIndex = indexOfFirstInstructionOrThrow(Opcode.CONST_STRING) + val replaceRegister = + getInstruction(replaceIndex).registerA + + replaceInstruction( + replaceIndex, + "const-string v$replaceRegister, \"$musicPackageName\"" + ) + } + } + + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/music/fingerprints/AppDeepLinkFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/music/fingerprints/AppDeepLinkFingerprint.kt new file mode 100644 index 000000000..d4d7d2330 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/general/music/fingerprints/AppDeepLinkFingerprint.kt @@ -0,0 +1,27 @@ +package app.revanced.patches.youtube.general.music.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.reference.FieldReference + +internal object AppDeepLinkFingerprint : MethodFingerprint( + returnType = "V", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + parameters = listOf("L", "Ljava/util/Map;"), + opcodes = listOf( + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.CONST_STRING, + ), + strings = listOf("android.intent.action.VIEW"), + customFingerprint = { methodDef, _ -> + methodDef.indexOfFirstInstruction { + getReference()?.name == "appDeepLinkEndpoint" + } >= 0 + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/navigation/NavigationBarComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/navigation/NavigationBarComponentsPatch.kt index 51d27430c..df78e197b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/navigation/NavigationBarComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/navigation/NavigationBarComponentsPatch.kt @@ -12,14 +12,18 @@ import app.revanced.patches.youtube.general.navigation.fingerprints.TranslucentN import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.navigation.NavigationBarHookPatch +import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode 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.reference.MethodReference @Suppress("unused") object NavigationBarComponentsPatch : BaseBytecodePatch( @@ -27,6 +31,7 @@ object NavigationBarComponentsPatch : BaseBytecodePatch( description = "Adds options to hide or change components related to the navigation bar.", dependencies = setOf( SettingsPatch::class, + SharedResourceIdPatch::class, NavigationBarHookPatch::class ), compatiblePackages = COMPATIBLE_PACKAGE, @@ -48,7 +53,7 @@ object NavigationBarComponentsPatch : BaseBytecodePatch( // region patch for enable translucent navigation bar if (SettingsPatch.upward1923) { - TranslucentNavigationBarFingerprint.literalInstructionBooleanHook( + TranslucentNavigationBarFingerprint.injectLiteralInstructionBooleanCall( 45630927, "$GENERAL_CLASS_DESCRIPTOR->enableTranslucentNavigationBar()Z" ) @@ -81,17 +86,23 @@ object NavigationBarComponentsPatch : BaseBytecodePatch( // endregion + // region patch for hide navigation bar + + NavigationBarHookPatch.addBottomBarContainerHook("$GENERAL_CLASS_DESCRIPTOR->hideNavigationBar(Landroid/view/View;)V") + + // endregion + // region patch for hide navigation buttons AutoMotiveFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = getStringInstructionIndex("Android Automotive") - 1 - val register = getInstruction(insertIndex).registerA + val insertIndex = indexOfFirstStringInstructionOrThrow("Android Automotive") - 1 + val insertRegister = getInstruction(insertIndex).registerA addInstructions( insertIndex, """ - invoke-static {v$register}, $GENERAL_CLASS_DESCRIPTOR->switchCreateWithNotificationButton(Z)Z - move-result v$register + invoke-static {v$insertRegister}, $GENERAL_CLASS_DESCRIPTOR->switchCreateWithNotificationButton(Z)Z + move-result v$insertRegister """ ) } @@ -103,7 +114,10 @@ object NavigationBarComponentsPatch : BaseBytecodePatch( PivotBarSetTextFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val targetIndex = getTargetIndexWithMethodReferenceNameOrThrow("setText") + val targetIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setText" + } val targetRegister = getInstruction(targetIndex).registerC addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/splashanimation/fingerprints/SplashAnimationFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/splashanimation/fingerprints/SplashAnimationFingerprint.kt index 59d0ec246..bc421d1c6 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/splashanimation/fingerprints/SplashAnimationFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/splashanimation/fingerprints/SplashAnimationFingerprint.kt @@ -2,13 +2,13 @@ package app.revanced.patches.youtube.general.splashanimation.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.DarkSplashAnimation -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue internal object SplashAnimationFingerprint : MethodFingerprint( returnType = "V", parameters = listOf("Landroid/os/Bundle;"), customFingerprint = { methodDef, _ -> methodDef.name == "onCreate" - && methodDef.containsWideLiteralInstructionIndex(DarkSplashAnimation) + && methodDef.containsWideLiteralInstructionValue(DarkSplashAnimation) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/splashanimation/fingerprints/StartUpResourceIdFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/splashanimation/fingerprints/StartUpResourceIdFingerprint.kt index c986eb741..339a27ecf 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/splashanimation/fingerprints/StartUpResourceIdFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/splashanimation/fingerprints/StartUpResourceIdFingerprint.kt @@ -2,7 +2,7 @@ package app.revanced.patches.youtube.general.splashanimation.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object StartUpResourceIdFingerprint : MethodFingerprint( @@ -10,7 +10,7 @@ internal object StartUpResourceIdFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, parameters = listOf("I"), customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(3) - && methodDef.containsWideLiteralInstructionIndex(4) + methodDef.containsWideLiteralInstructionValue(3) + && methodDef.containsWideLiteralInstructionValue(4) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/spoofappversion/SpoofAppVersionPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/spoofappversion/SpoofAppVersionPatch.kt index 5c53e03c1..54a4a0b0a 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/spoofappversion/SpoofAppVersionPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/spoofappversion/SpoofAppVersionPatch.kt @@ -2,11 +2,11 @@ package app.revanced.patches.youtube.general.spoofappversion import app.revanced.patcher.data.ResourceContext import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE +import app.revanced.patches.youtube.utils.settings.ResourceUtils.addEntryValues import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.util.patch.BaseResourcePatch -import org.w3c.dom.Element -@Suppress("DEPRECATION", "unused") +@Suppress("unused") object SpoofAppVersionPatch : BaseResourcePatch( name = "Spoof app version", description = "Adds options to spoof the YouTube client version. " + @@ -17,31 +17,20 @@ object SpoofAppVersionPatch : BaseResourcePatch( ), compatiblePackages = COMPATIBLE_PACKAGE ) { + private const val ATTRIBUTE_NAME_ENTRIES = + "revanced_spoof_app_version_target_entries" + + private const val ATTRIBUTE_NAME_ENTRY_VALUE = + "revanced_spoof_app_version_target_entry_values" + override fun execute(context: ResourceContext) { if (SettingsPatch.upward1834) { - context.appendChild( - arrayOf( - "revanced_spoof_app_version_target_entries" to "@string/revanced_spoof_app_version_target_entry_18_33_40", - "revanced_spoof_app_version_target_entry_values" to "18.33.40", - ) - ) - + context.appendAppVersion("18.33.40") if (SettingsPatch.upward1839) { - context.appendChild( - arrayOf( - "revanced_spoof_app_version_target_entries" to "@string/revanced_spoof_app_version_target_entry_18_38_45", - "revanced_spoof_app_version_target_entry_values" to "18.38.45" - ) - ) - + context.appendAppVersion("18.38.45") if (SettingsPatch.upward1849) { - context.appendChild( - arrayOf( - "revanced_spoof_app_version_target_entries" to "@string/revanced_spoof_app_version_target_entry_18_48_39", - "revanced_spoof_app_version_target_entry_values" to "18.48.39" - ) - ) + context.appendAppVersion("18.48.39") } } } @@ -60,25 +49,16 @@ object SpoofAppVersionPatch : BaseResourcePatch( SettingsPatch.updatePatchStatus(this) } - private fun ResourceContext.appendChild(entryArray: Array>) { - entryArray.map { (attributeName, attributeValue) -> - this.xmlEditor["res/values/arrays.xml"].use { editor -> - editor.file.apply { - val resourcesNode = getElementsByTagName("resources").item(0) as Element - - val newElement: Element = createElement("item") - for (i in 0 until resourcesNode.childNodes.length) { - val node = resourcesNode.childNodes.item(i) as? Element ?: continue - - if (node.getAttribute("name") == attributeName) { - newElement.appendChild(createTextNode(attributeValue)) - val firstChild = node.firstChild - - node.insertBefore(newElement, firstChild) - } - } - } - } - } + private fun ResourceContext.appendAppVersion(appVersion: String) { + addEntryValues( + ATTRIBUTE_NAME_ENTRIES, + "@string/revanced_spoof_app_version_target_entry_" + appVersion.replace(".", "_"), + prepend = false + ) + addEntryValues( + ATTRIBUTE_NAME_ENTRY_VALUE, + appVersion, + prepend = false + ) } } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/startpage/ChangeStartPagePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/startpage/ChangeStartPagePatch.kt index bca0fe45e..7412b16bd 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/startpage/ChangeStartPagePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/startpage/ChangeStartPagePatch.kt @@ -2,13 +2,20 @@ package app.revanced.patches.youtube.general.startpage import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patches.youtube.general.startpage.fingerprints.ShortcutsActivityFingerprint -import app.revanced.patches.youtube.general.startpage.fingerprints.UrlActivityFingerprint +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patches.youtube.general.startpage.fingerprints.BrowseIdFingerprint +import app.revanced.patches.youtube.general.startpage.fingerprints.IntentActionFingerprint import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE -import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR +import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_PATH import app.revanced.patches.youtube.utils.settings.SettingsPatch +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.StringReference @Suppress("unused") object ChangeStartPagePatch : BaseBytecodePatch( @@ -17,22 +24,37 @@ object ChangeStartPagePatch : BaseBytecodePatch( dependencies = setOf(SettingsPatch::class), compatiblePackages = COMPATIBLE_PACKAGE, fingerprints = setOf( - ShortcutsActivityFingerprint, - UrlActivityFingerprint + BrowseIdFingerprint, + IntentActionFingerprint, ) ) { + private const val INTEGRATIONS_CLASS_DESCRIPTOR = "$GENERAL_PATH/ChangeStartPagePatch;" + override fun execute(context: BytecodeContext) { - mapOf( - ShortcutsActivityFingerprint to "changeStartPageToShortcuts", - UrlActivityFingerprint to "changeStartPageToUrl" - ).forEach { (fingerprint, method) -> - fingerprint.resultOrThrow().mutableMethod.addInstruction( - 0, - "invoke-static { p1 }, $GENERAL_CLASS_DESCRIPTOR->$method(Landroid/content/Intent;)V" + // Hook browseId. + BrowseIdFingerprint.resultOrThrow().mutableMethod.apply { + val browseIdIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.CONST_STRING && + getReference()?.string == "FEwhat_to_watch" + } + val browseIdRegister = getInstruction(browseIdIndex).registerA + + addInstructions( + browseIdIndex + 1, """ + invoke-static { v$browseIdRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->overrideBrowseId(Ljava/lang/String;)Ljava/lang/String; + move-result-object v$browseIdRegister + """ ) } + // There is no browseId assigned to Shorts and Search. + // Just hook the Intent action. + IntentActionFingerprint.resultOrThrow().mutableMethod.addInstruction( + 0, + "invoke-static { p1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->overrideIntentAction(Landroid/content/Intent;)V" + ) + /** * Add settings */ diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/startpage/fingerprints/BrowseIdFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/startpage/fingerprints/BrowseIdFingerprint.kt new file mode 100644 index 000000000..f53490ac4 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/general/startpage/fingerprints/BrowseIdFingerprint.kt @@ -0,0 +1,15 @@ +package app.revanced.patches.youtube.general.startpage.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.Opcode + +internal object BrowseIdFingerprint : MethodFingerprint( + returnType = "Lcom/google/android/apps/youtube/app/common/ui/navigation/PaneDescriptor;", + parameters = emptyList(), + opcodes = listOf( + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.RETURN_OBJECT, + ), + strings = listOf("FEwhat_to_watch"), +) diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/startpage/fingerprints/ShortcutsActivityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/startpage/fingerprints/IntentActionFingerprint.kt similarity index 77% rename from src/main/kotlin/app/revanced/patches/youtube/general/startpage/fingerprints/ShortcutsActivityFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/general/startpage/fingerprints/IntentActionFingerprint.kt index c0bd15917..8d6292c7d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/startpage/fingerprints/ShortcutsActivityFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/startpage/fingerprints/IntentActionFingerprint.kt @@ -2,7 +2,7 @@ package app.revanced.patches.youtube.general.startpage.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint -internal object ShortcutsActivityFingerprint : MethodFingerprint( +internal object IntentActionFingerprint : MethodFingerprint( parameters = listOf("Landroid/content/Intent;"), strings = listOf("has_handled_intent"), ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/startpage/fingerprints/UrlActivityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/startpage/fingerprints/UrlActivityFingerprint.kt deleted file mode 100644 index 680ef6e29..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/general/startpage/fingerprints/UrlActivityFingerprint.kt +++ /dev/null @@ -1,11 +0,0 @@ -package app.revanced.patches.youtube.general.startpage.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint - -internal object UrlActivityFingerprint : MethodFingerprint( - parameters = listOf("Landroid/content/Intent;"), - customFingerprint = { methodDef, classDef -> - methodDef.name == "startActivity" - && classDef.type.endsWith("/Shell_HomeActivity;") - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/ToolBarComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/ToolBarComponentsPatch.kt index acc992511..911ecb988 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/ToolBarComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/ToolBarComponentsPatch.kt @@ -39,16 +39,17 @@ import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch.contexts import app.revanced.patches.youtube.utils.toolbar.ToolBarHookPatch import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT +import app.revanced.util.alsoResolve import app.revanced.util.doRecursively -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getTargetIndexWithReferenceOrThrow -import app.revanced.util.getTargetIndexWithReferenceReversedOrThrow +import app.revanced.util.findMethodOrThrow +import app.revanced.util.getReference import app.revanced.util.getWalkerMethod -import app.revanced.util.getWideLiteralInstructionIndex -import app.revanced.util.literalInstructionBooleanHook -import app.revanced.util.literalInstructionHook +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.patch.BaseBytecodePatch +import app.revanced.util.replaceLiteralInstructionCall import app.revanced.util.resultOrThrow import app.revanced.util.updatePatchStatus import com.android.tools.smali.dexlib2.Opcode @@ -106,7 +107,7 @@ object ToolBarComponentsPatch : BaseBytecodePatch( YtPremiumWordMarkHeader, YtWordMarkHeader ).forEach { literal -> - context.literalInstructionHook(literal, smaliInstruction) + context.replaceLiteralInstructionCall(literal, smaliInstruction) } // YouTube's headers have the form of AttributeSet, which is decoded from YouTube's built-in classes. @@ -114,8 +115,8 @@ object ToolBarComponentsPatch : BaseBytecodePatch( val attributeResolverMethodCall = attributeResolverMethod.definingClass + "->" + attributeResolverMethod.name + "(Landroid/content/Context;I)Landroid/graphics/drawable/Drawable;" - context.findClass(GENERAL_CLASS_DESCRIPTOR)!!.mutableClass.methods.single { method -> - method.name == "getHeaderDrawable" + context.findMethodOrThrow(GENERAL_CLASS_DESCRIPTOR) { + name == "getHeaderDrawable" }.addInstructions( 0, """ invoke-static {p0, p1}, $attributeResolverMethodCall @@ -125,13 +126,11 @@ object ToolBarComponentsPatch : BaseBytecodePatch( ) // The sidebar's header is lithoView. Add a listener to change it. - DrawerContentViewFingerprint.resolve( - context, - DrawerContentViewConstructorFingerprint.resultOrThrow().classDef - ) - DrawerContentViewFingerprint.resultOrThrow().let { + DrawerContentViewFingerprint.alsoResolve( + context, DrawerContentViewConstructorFingerprint + ).let { it.mutableMethod.apply { - val insertIndex = getTargetIndexWithMethodReferenceNameOrThrow("addView") + val insertIndex = DrawerContentViewFingerprint.indexOfAddViewInstruction(this) val insertRegister = getInstruction(insertIndex).registerD addInstruction( @@ -147,7 +146,7 @@ object ToolBarComponentsPatch : BaseBytecodePatch( setActionBarRingoMutableClass.methods.first { method -> MethodUtil.isConstructor(method) }.apply { - val insertIndex = getTargetIndexOrThrow(Opcode.IPUT_BOOLEAN) + val insertIndex = indexOfFirstInstructionOrThrow(Opcode.IPUT_BOOLEAN) val insertRegister = getInstruction(insertIndex).registerA addInstruction( @@ -172,7 +171,8 @@ object ToolBarComponentsPatch : BaseBytecodePatch( ActionBarRingoBackgroundFingerprint.resultOrThrow().let { ActionBarRingoTextFingerprint.resolve(context, it.classDef) it.mutableMethod.apply { - val viewIndex = getWideLiteralInstructionIndex(ActionBarRingoBackground) + 2 + val viewIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(ActionBarRingoBackground) + 2 val viewRegister = getInstruction(viewIndex).registerA addInstructions( @@ -281,16 +281,16 @@ object ToolBarComponentsPatch : BaseBytecodePatch( CreateSearchSuggestionsFingerprint.resultOrThrow().let { result -> result.mutableMethod.apply { - val relativeIndex = getWideLiteralInstructionIndex(40) - val replaceIndex = getTargetIndexWithReferenceReversedOrThrow( - relativeIndex, - "Landroid/widget/ImageView;->setVisibility(I)V" - ) - 1 + val relativeIndex = indexOfFirstWideLiteralInstructionValueOrThrow(40) + val replaceIndex = indexOfFirstInstructionReversedOrThrow(relativeIndex) { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.toString() == "Landroid/widget/ImageView;->setVisibility(I)V" + } - 1 - val jumpIndex = getTargetIndexWithReferenceOrThrow( - relativeIndex, - "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;" - ) + 4 + val jumpIndex = indexOfFirstInstructionOrThrow(relativeIndex) { + opcode == Opcode.INVOKE_STATIC && + getReference()?.toString() == "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;" + } + 4 val replaceIndexInstruction = getInstruction(replaceIndex) val replaceIndexReference = @@ -313,7 +313,7 @@ object ToolBarComponentsPatch : BaseBytecodePatch( // region patch for hide voice search button if (SettingsPatch.upward1928) { - ImageSearchButtonConfigFingerprint.literalInstructionBooleanHook( + ImageSearchButtonConfigFingerprint.injectLiteralInstructionBooleanCall( 45617544, "$GENERAL_CLASS_DESCRIPTOR->hideImageSearchButton(Z)Z" ) @@ -327,15 +327,15 @@ object ToolBarComponentsPatch : BaseBytecodePatch( // region patch for hide voice search button - SearchBarFingerprint.resolve( - context, - SearchBarParentFingerprint.resultOrThrow().classDef - ) - SearchBarFingerprint.resultOrThrow().let { + SearchBarFingerprint.alsoResolve( + context, SearchBarParentFingerprint + ).let { it.mutableMethod.apply { val startIndex = it.scanResult.patternScanResult!!.startIndex - val setVisibilityIndex = - getTargetIndexWithMethodReferenceNameOrThrow(startIndex, "setVisibility") + val setVisibilityIndex = indexOfFirstInstructionOrThrow(startIndex) { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setVisibility" + } val setVisibilityInstruction = getInstruction(setVisibilityIndex) @@ -349,12 +349,11 @@ object ToolBarComponentsPatch : BaseBytecodePatch( SearchResultFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val startIndex = getWideLiteralInstructionIndex(VoiceSearch) - val setOnClickListenerIndex = - getTargetIndexWithMethodReferenceNameOrThrow( - startIndex, - "setOnClickListener" - ) + val startIndex = indexOfFirstWideLiteralInstructionValueOrThrow(VoiceSearch) + val setOnClickListenerIndex = indexOfFirstInstructionOrThrow(startIndex) { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setOnClickListener" + } val viewRegister = getInstruction(setOnClickListenerIndex).registerC @@ -370,7 +369,7 @@ object ToolBarComponentsPatch : BaseBytecodePatch( // region patch for replace create button CreateButtonDrawableFingerprint.resultOrThrow().mutableMethod.apply { - val index = getWideLiteralInstructionIndex(YtOutlineVideoCamera) + val index = indexOfFirstWideLiteralInstructionValueOrThrow(YtOutlineVideoCamera) val register = getInstruction(index).registerA addInstructions( @@ -383,15 +382,14 @@ object ToolBarComponentsPatch : BaseBytecodePatch( ToolBarHookPatch.hook("$GENERAL_CLASS_DESCRIPTOR->replaceCreateButton") - val settingsClass = context.findClass("Shell_SettingsActivity") - ?: throw PatchException("Shell_SettingsActivity class not found.") - - settingsClass.mutableClass.methods.find { it.name == "onCreate" }?.apply { - addInstruction( - 0, - "invoke-static {p0}, $GENERAL_CLASS_DESCRIPTOR->setShellActivityTheme(Landroid/app/Activity;)V" - ) - } ?: throw PatchException("onCreate method not found.") + context.findMethodOrThrow( + "Lcom/google/android/apps/youtube/app/application/Shell_SettingsActivity;" + ) { + name == "onCreate" + }.addInstruction( + 0, + "invoke-static {p0}, $GENERAL_CLASS_DESCRIPTOR->setShellActivityTheme(Landroid/app/Activity;)V" + ) // endregion diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/ActionBarRingoBackgroundFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/ActionBarRingoBackgroundFingerprint.kt index 4288d5714..fd04fadfb 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/ActionBarRingoBackgroundFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/ActionBarRingoBackgroundFingerprint.kt @@ -3,7 +3,7 @@ package app.revanced.patches.youtube.general.toolbar.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.general.toolbar.fingerprints.ActionBarRingoBackgroundFingerprint.indexOfStaticInstruction import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ActionBarRingoBackground -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.Opcode @@ -13,7 +13,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference internal object ActionBarRingoBackgroundFingerprint : MethodFingerprint( returnType = "Landroid/view/View;", customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(ActionBarRingoBackground) && + methodDef.containsWideLiteralInstructionValue(ActionBarRingoBackground) && indexOfStaticInstruction(methodDef) >= 0 } ) { diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/DrawerContentViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/DrawerContentViewFingerprint.kt index 789f2b197..afda22c8d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/DrawerContentViewFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/DrawerContentViewFingerprint.kt @@ -1,9 +1,14 @@ package app.revanced.patches.youtube.general.toolbar.fingerprints -import app.revanced.util.fingerprint.MethodReferenceNameFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.youtube.general.toolbar.fingerprints.DrawerContentViewFingerprint.indexOfAddViewInstruction +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionReversed import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal object DrawerContentViewFingerprint : MethodReferenceNameFingerprint( +internal object DrawerContentViewFingerprint : MethodFingerprint( returnType = "V", parameters = listOf("L"), opcodes = listOf( @@ -12,5 +17,13 @@ internal object DrawerContentViewFingerprint : MethodReferenceNameFingerprint( Opcode.NEW_INSTANCE, Opcode.INVOKE_DIRECT, ), - reference = { "addView" } -) + customFingerprint = { methodDef, _ -> + indexOfAddViewInstruction(methodDef) >= 0 + } +) { + fun indexOfAddViewInstruction(methodDef: Method) = + methodDef.indexOfFirstInstructionReversed { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "addView" + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/SearchBarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/SearchBarFingerprint.kt index fd8eed5bb..facbc289b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/SearchBarFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/SearchBarFingerprint.kt @@ -1,9 +1,12 @@ package app.revanced.patches.youtube.general.toolbar.fingerprints -import app.revanced.util.fingerprint.MethodReferenceNameFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionReversed import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.reference.MethodReference -object SearchBarFingerprint : MethodReferenceNameFingerprint( +object SearchBarFingerprint : MethodFingerprint( returnType = "V", parameters = listOf("Ljava/lang/String;"), opcodes = listOf( @@ -12,5 +15,9 @@ object SearchBarFingerprint : MethodReferenceNameFingerprint( Opcode.IGET_BOOLEAN, Opcode.IF_EQZ ), - reference = { "isEmpty" } + customFingerprint = { methodDef, _ -> + methodDef.indexOfFirstInstructionReversed { + getReference()?.name == "isEmpty" + } >= 0 + } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/actionbuttons/ShortsActionButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/actionbuttons/ShortsActionButtonsPatch.kt index 624cf8f38..7a7c6fe7d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/actionbuttons/ShortsActionButtonsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/actionbuttons/ShortsActionButtonsPatch.kt @@ -23,6 +23,7 @@ object ShortsActionButtonsPatch : BaseResourcePatch( key = "IconType", default = DEFAULT_ICON, values = mapOf( + "Cairo" to DEFAULT_ICON, "Outline" to "outline", "OutlineCircle" to "outlinecircle", "Round" to DEFAULT_ICON, @@ -80,6 +81,11 @@ object ShortsActionButtonsPatch : BaseResourcePatch( ) } + if (iconType == DEFAULT_ICON) { + SettingsPatch.updatePatchStatus(this) + return + } + context.copyResources( "youtube/shorts/actionbuttons/shared", ResourceGroup( diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/CustomBrandingIconPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/CustomBrandingIconPatch.kt index d6873e128..992a11db1 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/CustomBrandingIconPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/CustomBrandingIconPatch.kt @@ -31,6 +31,9 @@ object CustomBrandingIconPatch : BaseResourcePatch( "MMT" to "mmt", "MMT Blue" to "mmt_blue", "MMT Green" to "mmt_green", + "MMT Orange" to "mmt_orange", + "MMT Pink" to "mmt_pink", + "MMT Turquoise" to "mmt_turquoise", "MMT Yellow" to "mmt_yellow", "Revancify Blue" to "revancify_blue", "Revancify Red" to "revancify_red", diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/doubletaplength/DoubleTapLengthPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/doubletaplength/DoubleTapLengthPatch.kt index 65bc0860e..ad981948c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/doubletaplength/DoubleTapLengthPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/doubletaplength/DoubleTapLengthPatch.kt @@ -56,8 +56,16 @@ object DoubleTapLengthPatch : BaseResourcePatch( ) for (index in 0 until splits.count()) { - context.addEntryValues(arrayPath, lengthElements[index], entryValueName) - context.addEntryValues(arrayPath, lengthElements[index], entriesName) + context.addEntryValues( + entryValueName, + lengthElements[index], + path = arrayPath + ) + context.addEntryValues( + entriesName, + lengthElements[index], + path = arrayPath + ) } SettingsPatch.updatePatchStatus(this) diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/shortcut/ShortcutPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/shortcut/ShortcutPatch.kt new file mode 100644 index 000000000..85c977cc0 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/shortcut/ShortcutPatch.kt @@ -0,0 +1,69 @@ +package app.revanced.patches.youtube.layout.shortcut + +import app.revanced.patcher.data.ResourceContext +import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.booleanPatchOption +import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE +import app.revanced.patches.youtube.utils.settings.SettingsPatch +import app.revanced.util.findElementByAttributeValueOrThrow +import app.revanced.util.patch.BaseResourcePatch +import org.w3c.dom.Element + +@Suppress("DEPRECATION", "unused") +object ShortcutPatch : BaseResourcePatch( + name = "Hide shortcuts", + description = "Remove, at compile time, the app shortcuts that appears when app icon is long pressed.", + dependencies = setOf(SettingsPatch::class), + compatiblePackages = COMPATIBLE_PACKAGE, + use = false +) { + private val Explore by booleanPatchOption( + key = "Explore", + default = false, + title = "Hide Explore", + description = "Hide Explore from shortcuts.", + required = true + ) + + private val Subscriptions by booleanPatchOption( + key = "Subscriptions", + default = false, + title = "Hide Subscriptions", + description = "Hide Subscriptions from shortcuts.", + required = true + ) + + private val Search by booleanPatchOption( + key = "Search", + default = false, + title = "Hide Search", + description = "Hide Search from shortcuts.", + required = true + ) + + private val Shorts by booleanPatchOption( + key = "Shorts", + default = true, + title = "Hide Shorts", + description = "Hide Shorts from shortcuts.", + required = true + ) + + override fun execute(context: ResourceContext) { + + this.options.values.forEach { options -> + if (options.value == true) { + context.xmlEditor["res/xml/main_shortcuts.xml"].use { editor -> + val shortcuts = editor.file.getElementsByTagName("shortcuts").item(0) as Element + val shortsItem = shortcuts.getElementsByTagName("shortcut") + .findElementByAttributeValueOrThrow( + "android:shortcutId", + "${options.key.lowercase()}-shortcut" + ) + shortsItem.parentNode.removeChild(shortsItem) + } + } + } + + SettingsPatch.updatePatchStatus(this) + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/visual/VisualPreferencesIconsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/visual/VisualPreferencesIconsPatch.kt index b1b122c3e..8d8ae9350 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/visual/VisualPreferencesIconsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/visual/VisualPreferencesIconsPatch.kt @@ -140,7 +140,7 @@ object VisualPreferencesIconsPatch : BaseResourcePatch( "revanced_hide_shorts_comments_button" to "revanced_hide_quick_actions_comment_button", "revanced_hide_shorts_dislike_button" to "revanced_preference_screen_ryd", "revanced_hide_shorts_like_button" to "revanced_hide_quick_actions_like_button", - "revanced_hide_shorts_navigation_bar" to "revanced_preference_screen_navigation_buttons", + "revanced_hide_shorts_navigation_bar" to "revanced_preference_screen_navigation_bar", "revanced_hide_shorts_remix_button" to "M 380.054 557.441 L 380.054 371.244 L 546.045 464.343 Z M 564.57 719.47 L 674.24 719.47 L 674.24 609.8 L 704.361 609.8 L 704.361 719.47 L 814.031 719.47 L 814.031 749.591 L 704.361 749.591 L 704.361 859.261 L 674.24 859.261 L 674.24 749.591 L 564.57 749.591 Z M 254.476 548.617 C 214.463 541.558 184.342 521.573 164.449 488.894 C 144.638 456.166 140.789 420.184 152.949 381.36 C 165.176 342.575 190.038 311.715 227.315 289.053 L 494.766 126.709 C 532.073 104.098 570.902 96.25 610.91 103.23 C 650.922 110.289 681.043 130.274 700.937 162.954 C 720.748 195.683 724.598 231.664 712.438 270.486 C 700.208 309.272 675.349 340.132 638.071 362.795 L 611.529 378.905 C 620.859 378.905 629.048 379.519 639.759 381.394 C 679.772 388.454 709.894 408.441 729.787 441.119 C 749.599 473.848 753.458 509.804 741.297 548.628 C 740.399 551.192 738.146 553.135 735.508 554.105 C 732.889 555.07 729.635 555.337 726.716 554.942 C 723.791 554.547 720.894 553.426 719.047 551.717 C 718.097 550.855 717.311 549.7 716.972 548.469 C 716.637 547.253 716.687 545.732 717.135 544.229 C 727.42 511.824 724.26 482.161 707.614 454.824 C 691.047 427.438 666.17 410.921 632.649 405.042 C 617.329 402.332 602.042 401.447 597.748 401.286 C 588.341 400.876 581.445 396.779 578.706 391.277 C 577.322 388.498 576.914 385.175 577.67 381.95 C 578.419 378.757 580.362 375.39 583.44 372.342 C 585.934 369.904 625.142 343.69 626.109 343.043 C 657.431 324.065 678.071 298.507 688.285 266.062 C 698.57 233.658 695.41 203.995 678.764 176.659 C 662.196 149.273 637.321 132.757 603.801 126.876 C 570.275 120.918 538.038 127.419 506.748 146.447 L 239.296 308.79 C 207.974 327.768 187.315 353.34 177.102 385.785 C 166.816 418.19 169.977 447.853 186.622 475.189 C 203.191 502.575 228.065 519.091 261.587 524.971 C 274.985 527.341 292.192 528.737 292.956 528.82 C 301.857 529.82 308.076 531.673 312.016 534.059 C 316.058 536.507 317.963 539.807 318.027 543.091 C 318.118 549.524 311.511 556.846 303.613 562.158 C 300.08 564.526 269.166 586.237 268.118 586.974 C 236.812 605.95 216.165 631.507 205.952 663.951 C 195.667 696.356 198.827 726.021 215.474 753.356 C 232.041 780.741 256.915 797.258 290.436 803.138 C 323.96 809.097 356.201 802.588 387.488 783.567 L 507.965 707.501 L 507.781 737.418 L 399.469 803.306 C 362.163 825.916 323.329 833.799 283.327 826.784 C 243.309 819.766 213.153 799.764 193.301 767.061 C 173.45 734.356 169.639 698.351 181.798 659.526 C 194.027 620.74 218.888 589.881 256.165 567.219 L 282.707 551.108 C 273.378 551.107 265.189 550.493 254.476 548.617 Z", "revanced_hide_shorts_share_button" to "M 582.272 263.479 L 773.48 478.672 L 774.07 479.336 L 774.66 480 L 774.07 480.664 L 773.48 481.328 L 582.272 696.521 L 580.524 698.488 L 578.776 700.455 L 578.776 549.565 L 546.994 549.565 C 413.517 549.519 306.714 583.081 218.867 653.513 L 215.61 656.123 L 212.353 658.734 L 214.074 654.931 L 215.795 651.128 C 278.284 513.232 389.516 433.944 551.428 410.119 L 578.776 405.986 L 578.776 264.807 M 548.994 181.22 L 548.994 380.383 L 547.283 380.633 C 416.228 399.594 324.882 452.742 261.305 525.152 C 197.703 597.506 164.544 683.009 145.423 775.231 C 238.974 645.857 358.678 579.473 546.994 579.347 L 548.994 579.347 L 548.994 778.78 L 814.576 480 L 548.994 181.22 Z", "revanced_hide_shorts_shelf_history" to "history_key", @@ -179,7 +179,7 @@ object VisualPreferencesIconsPatch : BaseResourcePatch( "revanced_preference_screen_import_export" to "M 300.38 743.08 L 258.69 701.38 Q 208.69 649.85 185.27 594.88 Q 161.85 539.92 161.85 484.77 Q 161.85 397.69 206.77 324.96 Q 251.69 252.23 327.31 211.77 Q 333.69 208.85 340.19 209.5 Q 346.69 210.15 349.38 216.54 Q 352.08 222.15 349.5 228.15 Q 346.92 234.15 341.31 237.08 Q 272.46 272.85 232.54 339.27 Q 192.62 405.69 192.62 484.77 Q 192.62 536.77 211.65 584.42 Q 230.69 632.08 272.69 672.38 L 322.69 720.92 L 322.69 606.23 Q 322.69 599.38 326.96 595.12 Q 331.23 590.85 338.08 590.85 Q 344.15 590.85 348.81 595.12 Q 353.46 599.38 353.46 606.23 L 353.46 746.15 Q 353.46 758.38 345.35 766.12 Q 337.23 773.85 325.77 773.85 L 185.85 773.85 Q 179 773.85 174.73 769.58 Q 170.46 765.31 170.46 758.46 Q 170.46 751.62 174.73 747.35 Q 179 743.08 185.85 743.08 L 300.38 743.08 Z M 638.08 239.08 L 638.08 353.77 Q 638.08 360.62 633.42 364.88 Q 628.77 369.15 622.69 369.15 Q 615.85 369.15 611.58 364.88 Q 607.31 360.62 607.31 353.77 L 607.31 213.85 Q 607.31 201.62 615.04 193.88 Q 622.77 186.15 635 186.15 L 774.15 186.15 Q 781 186.15 785.27 190.42 Q 789.54 194.69 789.54 201.54 Q 789.54 208.38 785.27 212.65 Q 781 216.92 774.15 216.92 L 659.38 216.92 L 701.31 258.62 Q 743.92 300.54 766.08 346.69 Q 788.23 392.85 793.31 439.08 L 763.31 439.08 Q 757.46 396.54 739.08 358.42 Q 720.69 320.31 688.08 287.62 L 638.08 239.08 Z M 700.77 832.31 Q 695.54 832.31 691.54 828.81 Q 687.54 825.31 686.54 819.31 L 686.38 803.54 Q 660.23 798.31 640.38 786.42 Q 620.54 774.54 606.77 758.23 L 592.92 766.85 Q 587.92 769.62 582.42 768.62 Q 576.92 767.62 574.69 763.39 L 569.85 756.77 Q 566.08 751.77 567.08 746.38 Q 568.08 741 572.31 737.77 L 586.23 727.31 Q 576.62 701.23 576.62 678.5 Q 576.62 655.77 586.23 629.69 L 572.31 619.23 Q 568.08 616 567.08 610.62 Q 566.08 605.23 569.85 600.23 L 574.69 592.62 Q 576.92 588.38 582.42 587.77 Q 587.92 587.15 592.92 589.92 L 606.77 598.54 Q 620.54 582.69 640.38 570.69 Q 660.23 558.69 686.38 553.46 L 686.54 537.46 Q 687.54 531.46 691.54 527.96 Q 695.54 524.46 700.77 524.46 L 705.31 524.46 Q 710.54 524.46 714.54 527.96 Q 718.54 531.46 719.54 537.46 L 719.69 553.46 Q 745.85 558.69 765.69 570.69 Q 785.54 582.69 799.31 597.77 L 813.92 589.92 Q 818.92 587.15 823.65 587.77 Q 828.38 588.38 831.38 592.62 L 836.23 600.23 Q 840 605.23 839 610.23 Q 838 615.23 833 619.23 L 819.85 629.69 Q 829.46 655.77 829.46 678.12 Q 829.46 700.46 819.85 727.31 L 833.77 737.77 Q 838 741 839 746.38 Q 840 751.77 836.23 756.77 L 831.38 763.39 Q 828.38 767.62 823.27 768.62 Q 818.15 769.62 813.15 766.85 L 799.31 758.23 Q 785.54 774.54 765.69 786.42 Q 745.85 798.31 719.69 803.54 L 719.54 819.31 Q 718.54 825.31 714.54 828.81 Q 710.54 832.31 705.31 832.31 L 700.77 832.31 Z M 702.92 774.23 Q 743.08 774.23 770.92 746.38 Q 798.77 718.54 798.77 678.38 Q 798.77 638.23 770.92 610 Q 743.08 581.77 702.92 581.77 Q 662 581.77 634.15 610 Q 606.31 638.23 606.31 678.38 Q 606.31 718.54 634.15 746.38 Q 662 774.23 702.92 774.23 Z", "revanced_preference_screen_miniplayer" to "offline_key", "revanced_preference_screen_misc" to "M 658.231 466.308 L 495.231 303.308 L 658.231 140.307 L 821.231 303.308 L 658.231 466.308 Z M 184.615 416.615 L 184.615 184.846 L 415.615 184.846 L 415.615 416.615 L 184.615 416.615 Z M 543.385 775.385 L 543.385 544.385 L 775.154 544.385 L 775.154 775.385 L 543.385 775.385 Z M 184.615 775.385 L 184.615 544.385 L 415.615 544.385 L 415.615 775.385 L 184.615 775.385 Z M 215.384 385.846 L 384.846 385.846 L 384.846 215.615 L 215.384 215.615 L 215.384 385.846 Z M 660.462 425.308 L 780.231 305.538 L 660.462 185 L 539.923 305.538 L 660.462 425.308 Z M 574.154 744.616 L 744.385 744.616 L 744.385 575.154 L 574.154 575.154 L 574.154 744.616 Z M 215.384 744.616 L 384.846 744.616 L 384.846 575.154 L 215.384 575.154 L 215.384 744.616 Z M 384.846 385.846 Z M 539.923 305.538 Z M 384.846 575.154 Z M 574.154 575.154 Z", - "revanced_preference_screen_navigation_buttons" to "M 160 640 L 160 320 L 800 320 L 800 466.154 L 769.231 466.154 L 769.231 350.769 L 190.769 350.769 L 190.769 609.231 L 601.538 609.231 L 601.538 640 L 160 640 Z M 190.769 609.231 L 190.769 350.769 L 190.769 609.231 Z M 871.692 758.308 L 718.462 605.308 L 718.462 740 L 687.692 740 L 687.692 552.308 L 875.385 552.308 L 875.385 583.077 L 740.462 583.077 L 892.923 737.077 L 871.692 758.308 Z", + "revanced_preference_screen_navigation_bar" to "M 160 640 L 160 320 L 800 320 L 800 466.154 L 769.231 466.154 L 769.231 350.769 L 190.769 350.769 L 190.769 609.231 L 601.538 609.231 L 601.538 640 L 160 640 Z M 190.769 609.231 L 190.769 350.769 L 190.769 609.231 Z M 871.692 758.308 L 718.462 605.308 L 718.462 740 L 687.692 740 L 687.692 552.308 L 875.385 552.308 L 875.385 583.077 L 740.462 583.077 L 892.923 737.077 L 871.692 758.308 Z", "revanced_preference_screen_patch_information" to "about_key", "revanced_preference_screen_player_buttons" to "M 495.308 769.231 L 175.384 769.231 Q 152.154 769.231 136.077 753.154 Q 120 737.077 120 713.846 L 120 255.384 Q 120 232.154 136.077 216.077 Q 152.154 200 175.384 200 L 790.923 200 Q 814.154 200 830.231 216.077 Q 846.308 232.154 846.308 255.384 L 846.308 452.154 L 815.539 452.154 L 815.539 255.384 Q 815.539 244.615 808.616 237.692 Q 801.693 230.769 790.923 230.769 L 175.384 230.769 Q 164.615 230.769 157.692 237.692 Q 150.769 244.615 150.769 255.384 L 150.769 713.846 Q 150.769 724.616 157.692 731.539 Q 164.615 738.462 175.384 738.462 L 495.308 738.462 L 495.308 769.231 Z M 407.308 624.539 L 407.308 344.692 L 621.846 484.615 L 407.308 624.539 Z M 721.539 832.308 L 720.385 803.539 Q 694.231 798.308 674.385 786.423 Q 654.539 774.539 640.769 758.231 L 615.692 772.847 L 595.308 745.77 L 620.231 727.308 Q 610.615 701.231 610.615 678.5 Q 610.615 655.77 620.231 629.693 L 595.308 611.231 L 615.692 583.154 L 640.769 598.539 Q 654.539 582.692 674.385 570.692 Q 694.231 558.692 720.385 553.462 L 721.539 524.462 L 752.308 524.462 L 753.693 553.462 Q 779.846 558.692 799.693 570.692 Q 819.539 582.692 833.308 597.769 L 858.385 583.154 L 878.77 611.231 L 853.846 629.693 Q 863.462 655.77 863.462 678.116 Q 863.462 700.462 853.846 727.308 L 878.77 745.77 L 858.385 772.847 L 833.308 758.231 Q 819.539 774.539 799.693 786.423 Q 779.846 798.308 753.693 803.539 L 752.308 832.308 L 721.539 832.308 Z M 736.923 774.231 Q 777.077 774.231 804.923 746.385 Q 832.769 718.539 832.769 678.385 Q 832.769 638.231 804.923 610 Q 777.077 581.769 736.923 581.769 Q 696 581.769 668.154 610 Q 640.308 638.231 640.308 678.385 Q 640.308 718.539 668.154 746.385 Q 696 774.231 736.923 774.231 Z", "revanced_preference_screen_player_flyout_menu" to "M 392.385 741.231 L 392.385 710.461 L 800 710.461 L 800 741.231 L 392.385 741.231 Z M 392.385 495.385 L 392.385 464.615 L 800 464.615 L 800 495.385 L 392.385 495.385 Z M 392.385 249.308 L 392.385 218.538 L 800 218.538 L 800 249.308 L 392.385 249.308 Z M 208.299 772.846 Q 188.209 772.846 174.22 759.063 Q 160.231 745.279 160.231 725.577 Q 160.231 705.875 174.13 691.976 Q 188.029 678.077 207.731 678.077 Q 227.433 678.077 241.216 692.451 Q 255 706.825 255 726.462 Q 255 745.273 241.282 759.06 Q 227.563 772.846 208.299 772.846 Z M 208.299 527 Q 188.209 527 174.22 512.92 Q 160.231 498.839 160.231 480 Q 160.231 461.161 174.377 447.08 Q 188.523 433 208.387 433 Q 227.427 433 241.213 447.08 Q 255 461.161 255 480 Q 255 498.839 241.282 512.92 Q 227.563 527 208.299 527 Z M 207.231 280.923 Q 188.391 280.923 174.311 266.843 Q 160.231 252.763 160.231 233.923 Q 160.231 215.084 174.311 201.003 Q 188.391 186.923 207.615 186.923 Q 226.839 186.923 240.92 201.003 Q 255 215.084 255 233.923 Q 255 252.763 240.968 266.843 Q 226.936 280.923 207.231 280.923 Z", diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatch.kt index 825b4496f..827458cb7 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatch.kt @@ -14,7 +14,6 @@ import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PAC import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.patches.youtube.video.information.VideoInformationPatch import app.revanced.util.findOpcodeIndicesReversed import app.revanced.util.getWalkerMethod import app.revanced.util.patch.BaseBytecodePatch @@ -31,7 +30,6 @@ object BackgroundPlaybackPatch : BaseBytecodePatch( description = "Removes restrictions on background playback, including for music and kids videos.", dependencies = setOf( PlayerTypeHookPatch::class, - VideoInformationPatch::class, SettingsPatch::class ), compatiblePackages = COMPATIBLE_PACKAGE, diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/OpenLinksDirectlyPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/OpenLinksDirectlyPatch.kt index 0846f8970..676f2caef 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/OpenLinksDirectlyPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/OpenLinksDirectlyPatch.kt @@ -8,10 +8,13 @@ import app.revanced.patches.youtube.misc.openlinksdirectly.fingerprints.OpenLink import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Suppress("unused") object OpenLinksDirectlyPatch : BaseBytecodePatch( @@ -32,7 +35,10 @@ object OpenLinksDirectlyPatch : BaseBytecodePatch( ).forEach { fingerprint -> fingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = getTargetIndexWithMethodReferenceNameOrThrow("parse") + val insertIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_STATIC && + getReference()?.name == "parse" + } val insertRegister = getInstruction(insertIndex).registerC diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/share/ShareSheetPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/share/ShareSheetPatch.kt index 58ec1dfb5..1e762dc4c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/share/ShareSheetPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/share/ShareSheetPatch.kt @@ -13,8 +13,8 @@ import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.BottomSheetRecyclerView import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -46,8 +46,8 @@ object ShareSheetPatch : BaseBytecodePatch( // Detects that the Share sheet panel has been invoked. BottomSheetRecyclerViewFingerprint.resultOrThrow().mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(BottomSheetRecyclerView) - val targetIndex = getTargetIndexOrThrow(constIndex, Opcode.CHECK_CAST) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(BottomSheetRecyclerView) + val targetIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.CHECK_CAST) val targetRegister = getInstruction(targetIndex).registerA addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/ambientmode/AmbientModeSwitchPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/ambientmode/AmbientModeSwitchPatch.kt index f0c43fd8d..f5179bfe7 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/ambientmode/AmbientModeSwitchPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/ambientmode/AmbientModeSwitchPatch.kt @@ -3,23 +3,22 @@ package app.revanced.patches.youtube.player.ambientmode import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.patch.PatchException import app.revanced.patches.youtube.player.ambientmode.fingerprints.AmbientModeInFullscreenFingerprint import app.revanced.patches.youtube.player.ambientmode.fingerprints.PowerSaveModeBroadcastReceiverFingerprint import app.revanced.patches.youtube.player.ambientmode.fingerprints.PowerSaveModeSyntheticFingerprint import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.findMethodOrThrow +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction -import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Suppress("unused") @@ -46,12 +45,12 @@ object AmbientModeSwitchPatch : BaseBytecodePatch( ).forEach { (fingerprint, reversed) -> fingerprint.resultOrThrow().mutableMethod.apply { val stringIndex = - getStringInstructionIndex("android.os.action.POWER_SAVE_MODE_CHANGED") + indexOfFirstStringInstructionOrThrow("android.os.action.POWER_SAVE_MODE_CHANGED") val targetIndex = if (reversed) - getTargetIndexReversedOrThrow(stringIndex, Opcode.INVOKE_DIRECT) + indexOfFirstInstructionReversedOrThrow(stringIndex, Opcode.INVOKE_DIRECT) else - getTargetIndexOrThrow(stringIndex, Opcode.INVOKE_DIRECT) + indexOfFirstInstructionOrThrow(stringIndex, Opcode.INVOKE_DIRECT) val targetClass = (getInstruction(targetIndex).reference as MethodReference).definingClass @@ -60,34 +59,37 @@ object AmbientModeSwitchPatch : BaseBytecodePatch( } syntheticClassList.distinct().forEach { className -> - context.findClass(className)?.mutableClass?.methods?.first { method -> - method.name == "accept" - }?.apply { - for (index in implementation!!.instructions.size - 1 downTo 0) { - val instruction = getInstruction(index) - if (instruction.opcode != Opcode.INVOKE_VIRTUAL) - continue - - if (((instruction as Instruction35c).reference as MethodReference).name != "isPowerSaveMode") - continue - - val register = getInstruction(index + 1).registerA - - addInstructions( - index + 2, """ - invoke-static {v$register}, $PLAYER_CLASS_DESCRIPTOR->bypassAmbientModeRestrictions(Z)Z - move-result v$register - """ - ) - } - } ?: throw PatchException("Could not find $className") + context.findMethodOrThrow(className) { + name == "accept" + }.apply { + implementation!!.instructions + .withIndex() + .filter { (_, instruction) -> + val reference = (instruction as? ReferenceInstruction)?.reference + instruction.opcode == Opcode.INVOKE_VIRTUAL && + reference is MethodReference && + reference.name == "isPowerSaveMode" + } + .map { (index, _) -> index } + .reversed() + .forEach { index -> + val register = getInstruction(index + 1).registerA + + addInstructions( + index + 2, """ + invoke-static {v$register}, $PLAYER_CLASS_DESCRIPTOR->bypassAmbientModeRestrictions(Z)Z + move-result v$register + """ + ) + } + } } // endregion // region patch for disable ambient mode in fullscreen - AmbientModeInFullscreenFingerprint.literalInstructionBooleanHook( + AmbientModeInFullscreenFingerprint.injectLiteralInstructionBooleanCall( 45389368, "$PLAYER_CLASS_DESCRIPTOR->disableAmbientModeInFullscreen()Z" ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/buttons/PlayerButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/buttons/PlayerButtonsPatch.kt index 81888b98b..69e42d03f 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/buttons/PlayerButtonsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/buttons/PlayerButtonsPatch.kt @@ -24,14 +24,14 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.FullS import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.PlayerCollapseButton import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TitleAnchor import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.instruction.RegisterRangeInstruction import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction -import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction3rc @Suppress("unused") object PlayerButtonsPatch : BaseBytecodePatch( @@ -63,9 +63,10 @@ object PlayerButtonsPatch : BaseBytecodePatch( LayoutConstructorFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(AutoNavToggle) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(AutoNavToggle) val constRegister = getInstruction(constIndex).registerA - val jumpIndex = getTargetIndexOrThrow(constIndex + 2, Opcode.INVOKE_VIRTUAL) + 1 + val jumpIndex = + indexOfFirstInstructionOrThrow(constIndex + 2, Opcode.INVOKE_VIRTUAL) + 1 addInstructionsWithLabels( constIndex, """ @@ -124,9 +125,9 @@ object PlayerButtonsPatch : BaseBytecodePatch( // region patch for hide collapse button TitleAnchorFingerprint.resultOrThrow().mutableMethod.apply { - val titleAnchorConstIndex = getWideLiteralInstructionIndex(TitleAnchor) + val titleAnchorConstIndex = indexOfFirstWideLiteralInstructionValueOrThrow(TitleAnchor) val titleAnchorIndex = - getTargetIndexOrThrow(titleAnchorConstIndex, Opcode.MOVE_RESULT_OBJECT) + indexOfFirstInstructionOrThrow(titleAnchorConstIndex, Opcode.MOVE_RESULT_OBJECT) val titleAnchorRegister = getInstruction(titleAnchorIndex).registerA @@ -136,9 +137,9 @@ object PlayerButtonsPatch : BaseBytecodePatch( ) val playerCollapseButtonConstIndex = - getWideLiteralInstructionIndex(PlayerCollapseButton) + indexOfFirstWideLiteralInstructionValueOrThrow(PlayerCollapseButton) val playerCollapseButtonIndex = - getTargetIndexOrThrow(playerCollapseButtonConstIndex, Opcode.CHECK_CAST) + indexOfFirstInstructionOrThrow(playerCollapseButtonConstIndex, Opcode.CHECK_CAST) val playerCollapseButtonRegister = getInstruction(playerCollapseButtonIndex).registerA @@ -159,7 +160,7 @@ object PlayerButtonsPatch : BaseBytecodePatch( (instruction.value as? WideLiteralInstruction)?.wideLiteral == FullScreenButton } val constIndex = buttonCalls.elementAt(buttonCalls.size - 1).index - val castIndex = getTargetIndexOrThrow(constIndex, Opcode.CHECK_CAST) + val castIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.CHECK_CAST) val insertIndex = castIndex + 1 val insertRegister = getInstruction(castIndex).registerA @@ -180,8 +181,8 @@ object PlayerButtonsPatch : BaseBytecodePatch( PlayerControlsVisibilityModelFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val callIndex = getTargetIndexOrThrow(Opcode.INVOKE_DIRECT_RANGE) - val callInstruction = getInstruction(callIndex) + val callIndex = indexOfFirstInstructionOrThrow(Opcode.INVOKE_DIRECT_RANGE) + val callInstruction = getInstruction(callIndex) val hasNextParameterRegister = callInstruction.startRegister + HAS_NEXT val hasPreviousParameterRegister = callInstruction.startRegister + HAS_PREVIOUS diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/FullScreenButtonFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/FullScreenButtonFingerprint.kt index 42acc32f1..09e41630f 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/FullScreenButtonFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/FullScreenButtonFingerprint.kt @@ -5,7 +5,7 @@ import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.CfFullscreenButton import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.FadeDurationFast import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.FullScreenButton -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object FullScreenButtonFingerprint : MethodFingerprint( @@ -13,10 +13,10 @@ internal object FullScreenButtonFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = listOf("Landroid/view/View;"), customFingerprint = handler@{ methodDef, _ -> - if (!methodDef.containsWideLiteralInstructionIndex(FullScreenButton)) + if (!methodDef.containsWideLiteralInstructionValue(FullScreenButton)) return@handler false - methodDef.containsWideLiteralInstructionIndex(FadeDurationFast) // YouTube 18.29.38 ~ YouTube 19.18.41 - || methodDef.containsWideLiteralInstructionIndex(CfFullscreenButton) // YouTube 19.19.39 ~ + methodDef.containsWideLiteralInstructionValue(FadeDurationFast) // YouTube 18.29.38 ~ YouTube 19.18.41 + || methodDef.containsWideLiteralInstructionValue(CfFullscreenButton) // YouTube 19.19.39 ~ }, ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/TitleAnchorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/TitleAnchorFingerprint.kt index 263e4264d..a6c5b2eaa 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/TitleAnchorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/TitleAnchorFingerprint.kt @@ -3,12 +3,12 @@ package app.revanced.patches.youtube.player.buttons.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.PlayerCollapseButton import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TitleAnchor -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue internal object TitleAnchorFingerprint : MethodFingerprint( returnType = "V", customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(PlayerCollapseButton) - && methodDef.containsWideLiteralInstructionIndex(TitleAnchor) + methodDef.containsWideLiteralInstructionValue(PlayerCollapseButton) + && methodDef.containsWideLiteralInstructionValue(TitleAnchor) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/comments/CommentsComponentPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/comments/CommentsComponentPatch.kt index 132063250..8add5c0f8 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/comments/CommentsComponentPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/comments/CommentsComponentPatch.kt @@ -12,9 +12,9 @@ import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow import app.revanced.util.getWalkerMethod -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -56,14 +56,15 @@ object CommentsComponentPatch : BaseBytecodePatch( ShortsLiveStreamEmojiPickerOnClickListenerFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val emojiPickerEndpointIndex = getWideLiteralInstructionIndex(126326492) + val emojiPickerEndpointIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(126326492) val emojiPickerOnClickListenerIndex = - getTargetIndexOrThrow(emojiPickerEndpointIndex, Opcode.INVOKE_DIRECT) + indexOfFirstInstructionOrThrow(emojiPickerEndpointIndex, Opcode.INVOKE_DIRECT) val emojiPickerOnClickListenerMethod = getWalkerMethod(context, emojiPickerOnClickListenerIndex) emojiPickerOnClickListenerMethod.apply { - val insertIndex = getTargetIndexOrThrow(Opcode.IF_EQZ) + val insertIndex = indexOfFirstInstructionOrThrow(Opcode.IF_EQZ) val insertRegister = getInstruction(insertIndex).registerA diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt index 454c38629..eca7754ce 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt @@ -12,7 +12,6 @@ import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.shared.fingerprints.StartVideoInformerFingerprint import app.revanced.patches.shared.litho.LithoFilterPatch import app.revanced.patches.youtube.player.components.fingerprints.CrowdfundingBoxFingerprint -import app.revanced.patches.youtube.player.components.fingerprints.EngagementPanelControllerFingerprint import app.revanced.patches.youtube.player.components.fingerprints.FilmStripOverlayConfigFingerprint import app.revanced.patches.youtube.player.components.fingerprints.FilmStripOverlayInteractionFingerprint import app.revanced.patches.youtube.player.components.fingerprints.FilmStripOverlayParentFingerprint @@ -34,6 +33,7 @@ import app.revanced.patches.youtube.player.components.fingerprints.WatermarkPare import app.revanced.patches.youtube.player.speedoverlay.SpeedOverlayPatch import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.controlsoverlay.ControlsOverlayConfigPatch +import app.revanced.patches.youtube.utils.fingerprints.EngagementPanelBuilderFingerprint import app.revanced.patches.youtube.utils.fingerprints.YouTubeControlsOverlayFingerprint import app.revanced.patches.youtube.utils.fix.suggestedvideoendscreen.SuggestedVideoEndScreenPatch import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH @@ -48,11 +48,12 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TapBl import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.video.information.VideoInformationPatch import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getWideLiteralInstructionIndex -import app.revanced.util.literalInstructionViewHook +import app.revanced.util.findMethodOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.injectLiteralInstructionViewCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -61,6 +62,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Suppress("unused") object PlayerComponentsPatch : BaseBytecodePatch( @@ -79,7 +81,7 @@ object PlayerComponentsPatch : BaseBytecodePatch( compatiblePackages = COMPATIBLE_PACKAGE, fingerprints = setOf( CrowdfundingBoxFingerprint, - EngagementPanelControllerFingerprint, + EngagementPanelBuilderFingerprint, FilmStripOverlayParentFingerprint, InfoCardsIncognitoFingerprint, LayoutCircleFingerprint, @@ -107,8 +109,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( YouTubeControlsOverlayFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(ScrimOverlay) - val targetIndex = getTargetIndexOrThrow(constIndex, Opcode.CHECK_CAST) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(ScrimOverlay) + val targetIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.CHECK_CAST) val targetParameter = getInstruction(targetIndex).reference val targetRegister = getInstruction(targetIndex).registerA @@ -144,20 +146,19 @@ object PlayerComponentsPatch : BaseBytecodePatch( if (fingerprint == StartVideoInformerFingerprint) { hookInitVideoPanel(1) } else { - val syntheticIndex = getTargetIndexOrThrow(Opcode.NEW_INSTANCE) + val syntheticIndex = + indexOfFirstInstructionOrThrow(Opcode.NEW_INSTANCE) val syntheticReference = getInstruction(syntheticIndex).reference.toString() - val syntheticClass = - context.findClass(syntheticReference)!!.mutableClass - syntheticClass.methods.find { method -> method.name == "onClick" } - ?.hookInitVideoPanel(0) - ?: throw PatchException("Could not find onClick method in $syntheticReference") + context.findMethodOrThrow(syntheticReference) { + name == "onClick" + }.hookInitVideoPanel(0) } } } - EngagementPanelControllerFingerprint.resultOrThrow().let { + EngagementPanelBuilderFingerprint.resultOrThrow().let { it.mutableMethod.apply { addInstructionsWithLabels( 0, """ @@ -228,7 +229,7 @@ object PlayerComponentsPatch : BaseBytecodePatch( DarkBackground, TapBloomView ).forEach { literal -> - QuickSeekOverlayFingerprint.literalInstructionViewHook( + QuickSeekOverlayFingerprint.injectLiteralInstructionViewCall( literal, smaliInstruction ) @@ -273,10 +274,10 @@ object PlayerComponentsPatch : BaseBytecodePatch( YouTubeControlsOverlayFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(FadeDurationFast) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(FadeDurationFast) val constRegister = getInstruction(constIndex).registerA val insertIndex = - getTargetIndexReversedOrThrow(constIndex, Opcode.INVOKE_VIRTUAL) + 1 + indexOfFirstInstructionReversedOrThrow(constIndex, Opcode.INVOKE_VIRTUAL) + 1 val jumpIndex = implementation!!.instructions.let { instruction -> insertIndex + instruction.subList(insertIndex, instruction.size - 1) .indexOfFirst { instructions -> @@ -341,11 +342,14 @@ object PlayerComponentsPatch : BaseBytecodePatch( YouTubeControlsOverlayFingerprint.resultOrThrow().let { result -> result.mutableMethod.apply { - val insertIndex = getWideLiteralInstructionIndex(SeekUndoEduOverlayStub) + val insertIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(SeekUndoEduOverlayStub) val insertRegister = getInstruction(insertIndex).registerA - val onClickListenerIndex = - getTargetIndexWithMethodReferenceNameOrThrow(insertIndex, "setOnClickListener") + val onClickListenerIndex = indexOfFirstInstructionOrThrow(insertIndex) { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setOnClickListener" + } val constComponent = getConstComponent(insertIndex, onClickListenerIndex - 1) if (constComponent.isNotEmpty()) { @@ -390,8 +394,10 @@ object PlayerComponentsPatch : BaseBytecodePatch( it.mutableClass.methods.find { method -> method.parameters == listOf("Landroid/view/View${'$'}OnClickListener;") }?.apply { - val setOnClickListenerIndex = - getTargetIndexWithMethodReferenceNameOrThrow("setOnClickListener") + val setOnClickListenerIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setOnClickListener" + } val setOnClickListenerRegister = getInstruction(setOnClickListenerIndex).registerC diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/QuickSeekOverlayFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/QuickSeekOverlayFingerprint.kt index b07040639..1b7cb1ffa 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/QuickSeekOverlayFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/QuickSeekOverlayFingerprint.kt @@ -3,13 +3,13 @@ package app.revanced.patches.youtube.player.components.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.DarkBackground import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TapBloomView -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue internal object QuickSeekOverlayFingerprint : MethodFingerprint( returnType = "V", parameters = emptyList(), customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(DarkBackground) - && methodDef.containsWideLiteralInstructionIndex(TapBloomView) + methodDef.containsWideLiteralInstructionValue(DarkBackground) + && methodDef.containsWideLiteralInstructionValue(TapBloomView) }, ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/descriptions/DescriptionComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/descriptions/DescriptionComponentsPatch.kt index 3ef3d2681..c16e31639 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/descriptions/DescriptionComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/descriptions/DescriptionComponentsPatch.kt @@ -20,10 +20,14 @@ import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch import app.revanced.patches.youtube.utils.recyclerview.BottomSheetRecyclerViewPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.alsoResolve +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Suppress("unused") object DescriptionComponentsPatch : BaseBytecodePatch( @@ -54,23 +58,23 @@ object DescriptionComponentsPatch : BaseBytecodePatch( // In order to maintain compatibility with YouTube v18.48.39 or previous versions, // This patch is applied only to the version after YouTube v18.49.37. if (SettingsPatch.upward1849) { - RollingNumberTextViewAnimationUpdateFingerprint.resolve( - context, - RollingNumberTextViewFingerprint.resultOrThrow().classDef - ) - RollingNumberTextViewAnimationUpdateFingerprint.resultOrThrow().let { + RollingNumberTextViewAnimationUpdateFingerprint.alsoResolve( + context, RollingNumberTextViewFingerprint + ).let { it.mutableMethod.apply { val freeRegister = implementation!!.registerCount - parameters.size - 2 val imageSpanIndex = it.scanResult.patternScanResult!!.startIndex - val setTextIndex = getTargetIndexWithMethodReferenceNameOrThrow("setText") - + val setTextIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setText" + } addInstruction(setTextIndex, "nop") addInstructionsWithLabels( imageSpanIndex, """ - invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->disableRollingNumberAnimations()Z - move-result v$freeRegister - if-nez v$freeRegister, :disable_animations - """, ExternalLabel("disable_animations", getInstruction(setTextIndex)) + invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->disableRollingNumberAnimations()Z + move-result v$freeRegister + if-nez v$freeRegister, :disable_animations + """, ExternalLabel("disable_animations", getInstruction(setTextIndex)) ) } } @@ -106,13 +110,11 @@ object DescriptionComponentsPatch : BaseBytecodePatch( } } - EngagementPanelTitleFingerprint.resolve( - context, - EngagementPanelTitleParentFingerprint.resultOrThrow().classDef - ) - EngagementPanelTitleFingerprint.resultOrThrow().mutableMethod.apply { - val contentDescriptionIndex = - getTargetIndexWithMethodReferenceNameOrThrow("setContentDescription") + EngagementPanelTitleFingerprint.alsoResolve( + context, EngagementPanelTitleParentFingerprint + ).mutableMethod.apply { + val contentDescriptionIndex = EngagementPanelTitleFingerprint + .indexOfContentDescriptionInstruction(this) val contentDescriptionRegister = getInstruction(contentDescriptionIndex).registerD diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/descriptions/fingerprints/EngagementPanelTitleFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/descriptions/fingerprints/EngagementPanelTitleFingerprint.kt index 723f7803e..4fee2997d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/descriptions/fingerprints/EngagementPanelTitleFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/descriptions/fingerprints/EngagementPanelTitleFingerprint.kt @@ -1,8 +1,22 @@ package app.revanced.patches.youtube.player.descriptions.fingerprints -import app.revanced.util.fingerprint.MethodReferenceNameFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.youtube.player.descriptions.fingerprints.EngagementPanelTitleFingerprint.indexOfContentDescriptionInstruction +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionReversed +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal object EngagementPanelTitleFingerprint : MethodReferenceNameFingerprint( +internal object EngagementPanelTitleFingerprint : MethodFingerprint( strings = listOf(". "), - reference = { "setContentDescription" } -) \ No newline at end of file + customFingerprint = { methodDef, _ -> + indexOfContentDescriptionInstruction(methodDef) >= 0 + } +) { + fun indexOfContentDescriptionInstruction(methodDef: Method) = + methodDef.indexOfFirstInstructionReversed { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setContentDescription" + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/hide/PlayerFlyoutMenuPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/hide/PlayerFlyoutMenuPatch.kt index 6688bbcae..5b48b2606 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/hide/PlayerFlyoutMenuPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/hide/PlayerFlyoutMenuPatch.kt @@ -16,12 +16,15 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.BottomSheetFooterText import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.literalInstructionBooleanHook -import app.revanced.util.literalInstructionViewHook +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall +import app.revanced.util.injectLiteralInstructionViewCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Suppress("unused") object PlayerFlyoutMenuPatch : BaseBytecodePatch( @@ -56,7 +59,7 @@ object PlayerFlyoutMenuPatch : BaseBytecodePatch( val smaliInstruction = """ invoke-static {v$REGISTER_TEMPLATE_REPLACEMENT}, $PLAYER_CLASS_DESCRIPTOR->$name(Landroid/view/View;)V """ - fingerprint.literalInstructionViewHook(BottomSheetFooterText, smaliInstruction) + fingerprint.injectLiteralInstructionViewCall(BottomSheetFooterText, smaliInstruction) } arrayOf( @@ -64,15 +67,17 @@ object PlayerFlyoutMenuPatch : BaseBytecodePatch( QualityMenuViewInflateFingerprint ).forEach { fingerprint -> fingerprint.resultOrThrow().mutableMethod.apply { - val insertIndex = getTargetIndexWithMethodReferenceNameOrThrow("addHeaderView") + val insertIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "addHeaderView" + } val insertRegister = getInstruction(insertIndex).registerD addInstructions( - insertIndex, - """ - invoke-static {v$insertRegister}, $PLAYER_CLASS_DESCRIPTOR->hidePlayerFlyoutMenuQualityHeader(Landroid/view/View;)Landroid/view/View; - move-result-object v$insertRegister - """ + insertIndex, """ + invoke-static {v$insertRegister}, $PLAYER_CLASS_DESCRIPTOR->hidePlayerFlyoutMenuQualityHeader(Landroid/view/View;)Landroid/view/View; + move-result-object v$insertRegister + """ ) } } @@ -95,7 +100,7 @@ object PlayerFlyoutMenuPatch : BaseBytecodePatch( SettingsPatch.updatePatchStatus(this) if (SettingsPatch.upward1839) { - PiPModeConfigFingerprint.literalInstructionBooleanHook( + PiPModeConfigFingerprint.injectLiteralInstructionBooleanCall( 45427407, "$PLAYER_CLASS_DESCRIPTOR->hidePiPModeMenu(Z)Z" ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/hide/fingerprints/CaptionsBottomSheetFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/hide/fingerprints/CaptionsBottomSheetFingerprint.kt index 5a1cbf5c5..4c086f4a2 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/hide/fingerprints/CaptionsBottomSheetFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/hide/fingerprints/CaptionsBottomSheetFingerprint.kt @@ -4,13 +4,13 @@ import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.BottomSheetFooterText import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.SubtitleMenuSettingsFooterInfo -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object CaptionsBottomSheetFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(BottomSheetFooterText) - && methodDef.containsWideLiteralInstructionIndex(SubtitleMenuSettingsFooterInfo) + methodDef.containsWideLiteralInstructionValue(BottomSheetFooterText) + && methodDef.containsWideLiteralInstructionValue(SubtitleMenuSettingsFooterInfo) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/toggle/ChangeTogglePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/toggle/ChangeTogglePatch.kt index 9140067b6..3a2d60ae2 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/toggle/ChangeTogglePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/toggle/ChangeTogglePatch.kt @@ -17,11 +17,10 @@ import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PAC import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.util.getReference -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow import app.revanced.util.indexOfFirstInstruction import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -139,13 +138,15 @@ object ChangeTogglePatch : BaseBytecodePatch( } val classRegister = getInstruction(iGetIndex).registerB - val stringIndex = getStringInstructionIndex("menu_item_cinematic_lighting") + val stringIndex = + indexOfFirstStringInstructionOrThrow("menu_item_cinematic_lighting") - val checkCastIndex = getTargetIndexReversedOrThrow(stringIndex, Opcode.CHECK_CAST) + val checkCastIndex = + indexOfFirstInstructionReversedOrThrow(stringIndex, Opcode.CHECK_CAST) val iGetObjectPrimaryIndex = - getTargetIndexReversedOrThrow(checkCastIndex, Opcode.IGET_OBJECT) + indexOfFirstInstructionReversedOrThrow(checkCastIndex, Opcode.IGET_OBJECT) val iGetObjectSecondaryIndex = - getTargetIndexOrThrow(checkCastIndex, Opcode.IGET_OBJECT) + indexOfFirstInstructionOrThrow(checkCastIndex, Opcode.IGET_OBJECT) val checkCastReference = getInstruction(checkCastIndex).reference @@ -154,14 +155,15 @@ object ChangeTogglePatch : BaseBytecodePatch( val iGetObjectSecondaryReference = getInstruction(iGetObjectSecondaryIndex).reference - val invokeVirtualIndex = getTargetIndexOrThrow(stringIndex, Opcode.INVOKE_VIRTUAL) + val invokeVirtualIndex = + indexOfFirstInstructionOrThrow(stringIndex, Opcode.INVOKE_VIRTUAL) val invokeVirtualInstruction = getInstruction(invokeVirtualIndex) val freeRegisterC = invokeVirtualInstruction.registerC val freeRegisterD = invokeVirtualInstruction.registerD val freeRegisterE = invokeVirtualInstruction.registerE - val insertIndex = getTargetIndexOrThrow(stringIndex, Opcode.RETURN_VOID) + val insertIndex = indexOfFirstInstructionOrThrow(stringIndex, Opcode.RETURN_VOID) addInstructionsWithLabels( insertIndex, """ diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/FullscreenComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/FullscreenComponentsPatch.kt index 8a7be9a31..4846391cc 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/FullscreenComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/FullscreenComponentsPatch.kt @@ -29,13 +29,12 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.AutoN import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.FullScreenEngagementPanel import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.QuickActionsElementContainer import app.revanced.patches.youtube.utils.settings.SettingsPatch +import app.revanced.util.findMethodOrThrow import app.revanced.util.getReference -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow import app.revanced.util.getWalkerMethod -import app.revanced.util.getWideLiteralInstructionIndex import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import app.revanced.util.updatePatchStatus @@ -80,8 +79,9 @@ object FullscreenComponentsPatch : BaseBytecodePatch( EngagementPanelFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val literalIndex = getWideLiteralInstructionIndex(FullScreenEngagementPanel) - val targetIndex = getTargetIndexOrThrow(literalIndex, Opcode.CHECK_CAST) + val literalIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(FullScreenEngagementPanel) + val targetIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.CHECK_CAST) val targetRegister = getInstruction(targetIndex).registerA addInstruction( @@ -94,7 +94,10 @@ object FullscreenComponentsPatch : BaseBytecodePatch( PlayerTitleViewFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = getTargetIndexWithMethodReferenceNameOrThrow("addView") + val insertIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "addView" + } val insertReference = getInstruction(insertIndex).reference.toString() if (!insertReference.startsWith("Landroid/widget/FrameLayout;")) @@ -115,9 +118,10 @@ object FullscreenComponentsPatch : BaseBytecodePatch( LayoutConstructorFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(AutoNavPreviewStub) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(AutoNavPreviewStub) val constRegister = getInstruction(constIndex).registerA - val jumpIndex = getTargetIndexOrThrow(constIndex + 2, Opcode.INVOKE_VIRTUAL) + 1 + val jumpIndex = + indexOfFirstInstructionOrThrow(constIndex + 2, Opcode.INVOKE_VIRTUAL) + 1 addInstructionsWithLabels( constIndex, """ @@ -159,7 +163,7 @@ object FullscreenComponentsPatch : BaseBytecodePatch( } val constIndex = containerCalls.elementAt(containerCalls.size - 1).index - val checkCastIndex = getTargetIndexOrThrow(constIndex, Opcode.CHECK_CAST) + val checkCastIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.CHECK_CAST) val insertRegister = getInstruction(checkCastIndex).registerA @@ -183,9 +187,11 @@ object FullscreenComponentsPatch : BaseBytecodePatch( YouTubeControlsOverlayFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val targetIndex = - getTargetIndexWithMethodReferenceNameOrThrow("setFocusableInTouchMode") - val walkerIndex = getTargetIndexOrThrow(targetIndex, Opcode.INVOKE_STATIC) + val targetIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setFocusableInTouchMode" + } + val walkerIndex = indexOfFirstInstructionOrThrow(targetIndex, Opcode.INVOKE_STATIC) val walkerMethod = getWalkerMethod(context, walkerIndex) walkerMethod.apply { @@ -209,14 +215,14 @@ object FullscreenComponentsPatch : BaseBytecodePatch( ClientSettingEndpointFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val getActivityIndex = getStringInstructionIndex("watch") + 2 + val getActivityIndex = indexOfFirstStringInstructionOrThrow("watch") + 2 val getActivityReference = getInstruction(getActivityIndex).reference val classRegister = getInstruction(getActivityIndex).registerB val watchDescriptorMethodIndex = - getStringInstructionIndex("start_watch_minimized") - 1 + indexOfFirstStringInstructionOrThrow("start_watch_minimized") - 1 val watchDescriptorRegister = getInstruction(watchDescriptorMethodIndex).registerD @@ -228,7 +234,7 @@ object FullscreenComponentsPatch : BaseBytecodePatch( ) // hooks Activity. - val insertIndex = getStringInstructionIndex("force_fullscreen") + val insertIndex = indexOfFirstStringInstructionOrThrow("force_fullscreen") val freeRegister = getInstruction(insertIndex).registerA addInstructions( @@ -244,21 +250,20 @@ object FullscreenComponentsPatch : BaseBytecodePatch( VideoPortraitParentFingerprint.resultOrThrow().let { it.mutableMethod.apply { val stringIndex = - getStringInstructionIndex("Acquiring NetLatencyActionLogger failed. taskId=") - val invokeIndex = getTargetIndexOrThrow(stringIndex, Opcode.INVOKE_INTERFACE) - val targetIndex = getTargetIndexOrThrow(invokeIndex, Opcode.CHECK_CAST) - val targetClass = context - .findClass(getInstruction(targetIndex).reference.toString())!! - .mutableClass + indexOfFirstStringInstructionOrThrow("Acquiring NetLatencyActionLogger failed. taskId=") + val invokeIndex = + indexOfFirstInstructionOrThrow(stringIndex, Opcode.INVOKE_INTERFACE) + val targetIndex = indexOfFirstInstructionOrThrow(invokeIndex, Opcode.CHECK_CAST) + val targetClass = + getInstruction(targetIndex).reference.toString() // add an instruction to check the vertical video - targetClass.methods.find { method -> method.parameters == listOf("I", "I", "Z") } - ?.apply { - addInstruction( - 1, - "invoke-static {p1, p2}, $PLAYER_CLASS_DESCRIPTOR->setVideoPortrait(II)V" - ) - } ?: throw PatchException("Could not find targetMethod") + context.findMethodOrThrow(targetClass) { + parameters == listOf("I", "I", "Z") + }.addInstruction( + 1, + "invoke-static {p1, p2}, $PLAYER_CLASS_DESCRIPTOR->setVideoPortrait(II)V" + ) } } @@ -275,14 +280,11 @@ object FullscreenComponentsPatch : BaseBytecodePatch( } val walkerMethod = getWalkerMethod(context, walkerIndex) - val targetClass = - context.findClass(walkerMethod.definingClass)!!.mutableClass - val constructorMethod = targetClass - .methods - .find { method -> - method.name == "" - && method.parameterTypes == listOf("Landroid/app/Activity;") - } ?: throw PatchException("Constructor method not found!") + val constructorMethod = + context.findMethodOrThrow(walkerMethod.definingClass) { + name == "" && + parameterTypes == listOf("Landroid/app/Activity;") + } arrayOf( walkerMethod, @@ -328,8 +330,9 @@ object FullscreenComponentsPatch : BaseBytecodePatch( BroadcastReceiverFingerprint.resultOrThrow().let { result -> result.mutableMethod.apply { val stringIndex = - getStringInstructionIndex("android.intent.action.SCREEN_ON") - val insertIndex = getTargetIndexOrThrow(stringIndex, Opcode.IF_EQZ) + 1 + indexOfFirstStringInstructionOrThrow("android.intent.action.SCREEN_ON") + val insertIndex = + indexOfFirstInstructionOrThrow(stringIndex, Opcode.IF_EQZ) + 1 addInstruction( insertIndex, diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/fingerprints/PlayerTitleViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/fingerprints/PlayerTitleViewFingerprint.kt index 9529c1de9..1f8cc8b05 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/fingerprints/PlayerTitleViewFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/fingerprints/PlayerTitleViewFingerprint.kt @@ -1,12 +1,9 @@ package app.revanced.patches.youtube.player.fullscreen.fingerprints -import app.revanced.patcher.extensions.or import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.PlayerVideoTitleView import app.revanced.util.fingerprint.LiteralValueFingerprint -import com.android.tools.smali.dexlib2.AccessFlags internal object PlayerTitleViewFingerprint : LiteralValueFingerprint( - accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, returnType = "V", literalSupplier = { PlayerVideoTitleView } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/hapticfeedback/HapticFeedBackPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/hapticfeedback/HapticFeedBackPatch.kt index c1568aef0..2712908f8 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/hapticfeedback/HapticFeedBackPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/hapticfeedback/HapticFeedBackPatch.kt @@ -13,7 +13,7 @@ import app.revanced.patches.youtube.player.hapticfeedback.fingerprints.ZoomHapti import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -65,7 +65,7 @@ object HapticFeedBackPatch : BaseBytecodePatch( var register = 0 if (name == "run") { - index = getTargetIndexOrThrow(Opcode.SGET) + index = indexOfFirstInstructionOrThrow(Opcode.SGET) register = getInstruction(index).registerA } diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/seekbar/SeekbarComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/seekbar/SeekbarComponentsPatch.kt index 04a6e3b86..6679ff1ae 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/seekbar/SeekbarComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/seekbar/SeekbarComponentsPatch.kt @@ -8,7 +8,6 @@ import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.smali.ExternalLabel -import app.revanced.patches.music.player.components.PlayerComponentsResourcePatch import app.revanced.patches.shared.drawable.DrawableColorPatch import app.revanced.patches.youtube.player.seekbar.fingerprints.CairoSeekbarConfigFingerprint import app.revanced.patches.youtube.player.seekbar.fingerprints.ControlsOverlayStyleFingerprint @@ -31,17 +30,15 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.Inlin import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelTimeBarPlayedColor import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch.contexts -import app.revanced.patches.youtube.utils.settings.SettingsPatch.updatePatchStatus import app.revanced.patches.youtube.video.information.VideoInformationPatch import app.revanced.util.* import app.revanced.util.patch.BaseBytecodePatch import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction35c -import com.android.tools.smali.dexlib2.dexbacked.reference.DexBackedMethodReference import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference import org.w3c.dom.Element @Suppress("DEPRECATION", "unused") @@ -95,14 +92,15 @@ object SeekbarComponentsPatch : BaseBytecodePatch( SeekbarTappingFingerprint.resultOrThrow().let { it.mutableMethod.apply { val tapSeekIndex = it.scanResult.patternScanResult!!.startIndex + 1 - val tapSeekReference = getInstruction(tapSeekIndex).reference - val tapSeekClass = - context - .findClass((tapSeekReference as DexBackedMethodReference).definingClass)!! - .mutableClass - val tapSeekMethods = mutableMapOf() - - for (method in tapSeekClass.methods) { + val tapSeekClass = getInstruction(tapSeekIndex) + .getReference()!! + .definingClass + + val tapSeekMethods = context.findMethodsOrThrow(tapSeekClass) + var pMethodCall = "" + var oMethodCall = "" + + for (method in tapSeekMethods) { if (method.implementation == null) continue @@ -121,15 +119,17 @@ object SeekbarComponentsPatch : BaseBytecodePatch( // method founds if (literal == 1) - tapSeekMethods["P"] = method + pMethodCall = "${method.definingClass}->${method.name}(I)V" else if (literal == 2) - tapSeekMethods["O"] = method + oMethodCall = "${method.definingClass}->${method.name}(I)V" } - val pMethod = tapSeekMethods["P"] - ?: throw PatchException("pMethod not found") - val oMethod = tapSeekMethods["O"] - ?: throw PatchException("oMethod not found") + if (pMethodCall.isEmpty()) { + throw PatchException("pMethod not found") + } + if (oMethodCall.isEmpty()) { + throw PatchException("oMethod not found") + } val insertIndex = it.scanResult.patternScanResult!!.startIndex + 2 @@ -138,8 +138,8 @@ object SeekbarComponentsPatch : BaseBytecodePatch( invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->enableSeekbarTapping()Z move-result v0 if-eqz v0, :disabled - invoke-virtual { p0, v2 }, ${oMethod.definingClass}->${oMethod.name}(I)V - invoke-virtual { p0, v2 }, ${pMethod.definingClass}->${pMethod.name}(I)V + invoke-virtual { p0, v2 }, $pMethodCall + invoke-virtual { p0, v2 }, $oMethodCall """, ExternalLabel("disabled", getInstruction(insertIndex)) ) } @@ -151,11 +151,14 @@ object SeekbarComponentsPatch : BaseBytecodePatch( TotalTimeFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val charSequenceIndex = - getTargetIndexWithMethodReferenceNameOrThrow("getString") + 1 + val charSequenceIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "getString" + } + 1 val charSequenceRegister = getInstruction(charSequenceIndex).registerA - val textViewIndex = getTargetIndexWithMethodReferenceNameOrThrow("getText") + val textViewIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "getText" + } val textViewRegister = getInstruction(textViewIndex).registerC @@ -174,12 +177,12 @@ object SeekbarComponentsPatch : BaseBytecodePatch( // region patch for seekbar color PlayerSeekbarColorFingerprint.resultOrThrow().mutableMethod.apply { - hook(getWideLiteralInstructionIndex(InlineTimeBarColorizedBarPlayedColorDark) + 2) - hook(getWideLiteralInstructionIndex(InlineTimeBarPlayedNotHighlightedColor) + 2) + hook(InlineTimeBarColorizedBarPlayedColorDark) + hook(InlineTimeBarPlayedNotHighlightedColor) } ShortsSeekbarColorFingerprint.resultOrThrow().mutableMethod.apply { - hook(getWideLiteralInstructionIndex(ReelTimeBarPlayedColor) + 2) + hook(ReelTimeBarPlayedColor) } ControlsOverlayStyleFingerprint.resultOrThrow().let { @@ -237,7 +240,7 @@ object SeekbarComponentsPatch : BaseBytecodePatch( PlayerButtonsVisibilityFingerprint.resultOrThrow().let { it.mutableMethod.apply { val freeRegister = implementation!!.registerCount - parameters.size - 2 - val viewIndex = getTargetIndexOrThrow(Opcode.INVOKE_INTERFACE) + val viewIndex = indexOfFirstInstructionOrThrow(Opcode.INVOKE_INTERFACE) val viewRegister = getInstruction(viewIndex).registerD addInstructionsWithLabels( @@ -296,7 +299,7 @@ object SeekbarComponentsPatch : BaseBytecodePatch( // region patch for restore old seekbar thumbnails ThumbnailPreviewConfigFingerprint.result?.let { - ThumbnailPreviewConfigFingerprint.literalInstructionBooleanHook( + ThumbnailPreviewConfigFingerprint.injectLiteralInstructionBooleanCall( 45398577, "$PLAYER_CLASS_DESCRIPTOR->restoreOldSeekbarThumbnails()Z" ) @@ -310,7 +313,7 @@ object SeekbarComponentsPatch : BaseBytecodePatch( // region patch for enable cairo seekbar if (SettingsPatch.upward1923) { - CairoSeekbarConfigFingerprint.literalInstructionBooleanHook( + CairoSeekbarConfigFingerprint.injectLiteralInstructionBooleanCall( 45617850, "$PLAYER_CLASS_DESCRIPTOR->enableCairoSeekbar()Z" ) @@ -328,7 +331,8 @@ object SeekbarComponentsPatch : BaseBytecodePatch( SettingsPatch.updatePatchStatus(this) } - private fun MutableMethod.hook(insertIndex: Int) { + private fun MutableMethod.hook(literal: Long) { + val insertIndex = indexOfFirstWideLiteralInstructionValueOrThrow(literal) + 2 val insertRegister = getInstruction(insertIndex).registerA addInstructions( diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/SpeedOverlayPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/SpeedOverlayPatch.kt index 2c6f1ef1b..ae20d453e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/SpeedOverlayPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/SpeedOverlayPatch.kt @@ -6,7 +6,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.smali.ExternalLabel @@ -15,18 +14,17 @@ import app.revanced.patches.youtube.player.speedoverlay.fingerprints.NextGenWatc import app.revanced.patches.youtube.player.speedoverlay.fingerprints.RestoreSlideToSeekBehaviorFingerprint import app.revanced.patches.youtube.player.speedoverlay.fingerprints.SlideToSeekMotionEventFingerprint import app.revanced.patches.youtube.player.speedoverlay.fingerprints.SpeedOverlayFingerprint +import app.revanced.patches.youtube.player.speedoverlay.fingerprints.SpeedOverlayFloatValueFingerprint import app.revanced.patches.youtube.player.speedoverlay.fingerprints.SpeedOverlayTextValueFingerprint -import app.revanced.patches.youtube.player.speedoverlay.fingerprints.SpeedOverlayValueFingerprint import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch +import app.revanced.util.alsoResolve +import app.revanced.util.findMethodOrThrow import app.revanced.util.getReference -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameReversedOrThrow import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @@ -35,6 +33,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Patch(dependencies = [SharedResourceIdPatch::class]) object SpeedOverlayPatch : BytecodePatch( @@ -43,8 +42,8 @@ object SpeedOverlayPatch : BytecodePatch( NextGenWatchLayoutFingerprint, RestoreSlideToSeekBehaviorFingerprint, SpeedOverlayFingerprint, + SpeedOverlayFloatValueFingerprint, SpeedOverlayTextValueFingerprint, - SpeedOverlayValueFingerprint, ) ) { override fun execute(context: BytecodeContext) { @@ -52,36 +51,33 @@ object SpeedOverlayPatch : BytecodePatch( val restoreSlideToSeekBehaviorFingerprintResult = RestoreSlideToSeekBehaviorFingerprint.result val speedOverlayFingerprintResult = SpeedOverlayFingerprint.result - val speedOverlayValueFingerprintResult = SpeedOverlayValueFingerprint.result + val speedOverlayFloatValueFingerprintResult = SpeedOverlayFloatValueFingerprint.result val resolvable = restoreSlideToSeekBehaviorFingerprintResult != null && speedOverlayFingerprintResult != null - && speedOverlayValueFingerprintResult != null + && speedOverlayFloatValueFingerprintResult != null if (resolvable) { - // Legacy method. // Used on YouTube 18.29.38 ~ YouTube 19.17.41 - // region patch for disable speed overlay + // region patch for Disable speed overlay (Enable slide to seek) mapOf( RestoreSlideToSeekBehaviorFingerprint to 45411329, SpeedOverlayFingerprint to 45411330 ).forEach { (fingerprint, literal) -> - fingerprint.result!!.let { - fingerprint.literalInstructionBooleanHook( - literal, - "$PLAYER_CLASS_DESCRIPTOR->disableSpeedOverlay(Z)Z" - ) - } + fingerprint.injectLiteralInstructionBooleanCall( + literal, + "$PLAYER_CLASS_DESCRIPTOR->disableSpeedOverlay(Z)Z" + ) } // endregion - // region patch for custom speed overlay value + // region patch for Custom speed overlay float value - speedOverlayValueFingerprintResult!!.let { + speedOverlayFloatValueFingerprintResult!!.let { it.mutableMethod.apply { val index = it.scanResult.patternScanResult!!.startIndex val register = getInstruction(index).registerA @@ -98,13 +94,18 @@ object SpeedOverlayPatch : BytecodePatch( // endregion } else { - // New method. // Used on YouTube 19.18.41~ - NextGenWatchLayoutFingerprint.resultOrThrow().mutableMethod.apply { - val booleanValueIndex = getTargetIndexWithMethodReferenceNameOrThrow("booleanValue") + // region patch for Disable speed overlay (Enable slide to seek) - val insertIndex = findIGetIndex(booleanValueIndex - 10, booleanValueIndex) + NextGenWatchLayoutFingerprint.resultOrThrow().mutableMethod.apply { + val booleanValueIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "booleanValue" + } + val insertIndex = indexOfFirstInstructionOrThrow(booleanValueIndex - 10) { + opcode == Opcode.IGET_OBJECT + && getReference()?.definingClass == definingClass + } val insertInstruction = getInstruction(insertIndex) val insertReference = getInstruction(insertIndex).reference @@ -113,77 +114,100 @@ object SpeedOverlayPatch : BytecodePatch( "iget-object v${insertInstruction.registerA}, v${insertInstruction.registerB}, $insertReference" ) - val jumpIndex = findIGetIndex(booleanValueIndex, booleanValueIndex + 10) + val jumpIndex = indexOfFirstInstructionOrThrow(booleanValueIndex) { + opcode == Opcode.IGET_OBJECT + && getReference()?.definingClass == definingClass + } hook(insertIndex + 1, insertInstruction.registerA, jumpIndex) } - SlideToSeekMotionEventFingerprint.resolve( - context, - HorizontalTouchOffsetConstructorFingerprint.resultOrThrow().classDef - ) - SlideToSeekMotionEventFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - val scanResult = it.scanResult.patternScanResult!! + val (slideToSeekBooleanMethod, slideToSeekSyntheticMethod) = + SlideToSeekMotionEventFingerprint.alsoResolve( + context, HorizontalTouchOffsetConstructorFingerprint + ).let { + with(it.mutableMethod) { + val scanResult = it.scanResult.patternScanResult!! + val jumpIndex = scanResult.endIndex + 1 + val insertIndex = scanResult.endIndex - 1 + val insertRegister = + getInstruction(insertIndex).registerA + + hook(insertIndex, insertRegister, jumpIndex) + + val slideToSeekBooleanMethod = + getWalkerMethod(context, scanResult.startIndex + 1) + + val slideToSeekConstructorMethod = + context.findMethodOrThrow(slideToSeekBooleanMethod.definingClass) - val slideToSeekBooleanIndex = scanResult.startIndex + 1 - slideToSeekBooleanMethod = getWalkerMethod(context, slideToSeekBooleanIndex) + val slideToSeekSyntheticIndex = slideToSeekConstructorMethod + .indexOfFirstInstructionReversedOrThrow { + opcode == Opcode.NEW_INSTANCE + } - val jumpIndex = scanResult.endIndex + 1 - val insertIndex = scanResult.endIndex - 1 - val insertRegister = - getInstruction(insertIndex).registerA + val slideToSeekSyntheticClass = slideToSeekConstructorMethod + .getInstruction(slideToSeekSyntheticIndex) + .reference + .toString() - hook(insertIndex, insertRegister, jumpIndex) + val slideToSeekSyntheticMethod = + context.findMethodOrThrow(slideToSeekSyntheticClass) { + name == "run" + } + + Pair(slideToSeekBooleanMethod, slideToSeekSyntheticMethod) + } } - } slideToSeekBooleanMethod.apply { - var insertIndex = getTargetIndexOrThrow(Opcode.IGET_OBJECT) - var insertRegister = getInstruction(insertIndex).registerA - var jumpIndex = getTargetIndexReversedOrThrow(Opcode.INVOKE_VIRTUAL) + val insertIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.IGET_OBJECT + } + val insertRegister = getInstruction(insertIndex).registerA + val jumpIndex = indexOfFirstInstructionReversedOrThrow { + opcode == Opcode.INVOKE_VIRTUAL + } hook(insertIndex, insertRegister, jumpIndex) + } - val constructorMethod = - context.findClass(definingClass)?.mutableClass - ?.methods?.find { method -> method.name == "" } - ?: throw PatchException("Could not find constructor method") - - constructorMethod.apply { - val syntheticIndex = getTargetIndexReversedOrThrow(Opcode.NEW_INSTANCE) - val syntheticClass = - getInstruction(syntheticIndex).reference.toString() - - val syntheticMethod = - context.findClass(syntheticClass)?.mutableClass - ?.methods?.find { method -> method.name == "run" } - ?: throw PatchException("Could not find synthetic method") - - syntheticMethod.apply { - val speedOverlayValueIndex = - indexOfFirstInstructionOrThrow { (this as? NarrowLiteralInstruction)?.narrowLiteral == 2.0f.toRawBits() } - val speedOverlayValueRegister = - getInstruction(speedOverlayValueIndex).registerA - - addInstructions( - speedOverlayValueIndex + 1, """ - invoke-static {v$speedOverlayValueRegister}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayValue(F)F - move-result v$speedOverlayValueRegister - """ - ) - - insertIndex = getTargetIndexWithMethodReferenceNameReversedOrThrow( - speedOverlayValueIndex, - "removeCallbacks" - ) + 1 - insertRegister = - getInstruction(insertIndex - 1).registerC - jumpIndex = - getTargetIndexOrThrow(speedOverlayValueIndex, Opcode.RETURN_VOID) + 1 - hook(insertIndex, insertRegister, jumpIndex) - } + slideToSeekSyntheticMethod.apply { + val speedOverlayFloatValueIndex = indexOfFirstInstructionOrThrow { + (this as? NarrowLiteralInstruction)?.narrowLiteral == 2.0f.toRawBits() } + val insertIndex = + indexOfFirstInstructionReversedOrThrow(speedOverlayFloatValueIndex) { + getReference()?.name == "removeCallbacks" + } + 1 + val insertRegister = + getInstruction(insertIndex - 1).registerC + val jumpIndex = + indexOfFirstInstructionOrThrow( + speedOverlayFloatValueIndex, + Opcode.RETURN_VOID + ) + 1 + + hook(insertIndex, insertRegister, jumpIndex) + } + + // endregion + + // region patch for Custom speed overlay float value + + slideToSeekSyntheticMethod.apply { + val speedOverlayFloatValueIndex = indexOfFirstInstructionOrThrow { + (this as? NarrowLiteralInstruction)?.narrowLiteral == 2.0f.toRawBits() + } + val speedOverlayFloatValueRegister = + getInstruction(speedOverlayFloatValueIndex).registerA + + addInstructions( + speedOverlayFloatValueIndex + 1, """ + invoke-static {v$speedOverlayFloatValueRegister}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayValue(F)F + move-result v$speedOverlayFloatValueRegister + """ + ) } SpeedOverlayTextValueFingerprint.resultOrThrow().let { @@ -200,11 +224,12 @@ object SpeedOverlayPatch : BytecodePatch( ) } } + + // endregion + } } - private lateinit var slideToSeekBooleanMethod: MutableMethod - // restore slide to seek private fun MutableMethod.hook( insertIndex: Int, @@ -220,14 +245,4 @@ object SpeedOverlayPatch : BytecodePatch( """, ExternalLabel("disable", getInstruction(jumpIndex)) ) } - - private fun MutableMethod.findIGetIndex( - startIndex: Int, - endIndex: Int - ): Int = implementation!!.instructions.let { instruction -> - startIndex + instruction.subList(startIndex, endIndex).indexOfFirst { - it.opcode == Opcode.IGET_OBJECT - && it.getReference()?.definingClass == definingClass - } - } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/NextGenWatchLayoutFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/NextGenWatchLayoutFingerprint.kt index f5ef60b0c..4e54b4a7e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/NextGenWatchLayoutFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/NextGenWatchLayoutFingerprint.kt @@ -2,8 +2,10 @@ package app.revanced.patches.youtube.player.speedoverlay.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.containsMethodReferenceNameInstructionIndex +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.iface.reference.MethodReference internal object NextGenWatchLayoutFingerprint : MethodFingerprint( returnType = "Z", @@ -13,6 +15,8 @@ internal object NextGenWatchLayoutFingerprint : MethodFingerprint( if (methodDef.definingClass != "Lcom/google/android/apps/youtube/app/watch/nextgenwatch/ui/NextGenWatchLayout;") return@handler false - methodDef.containsMethodReferenceNameInstructionIndex("booleanValue") + methodDef.indexOfFirstInstruction { + getReference()?.name == "booleanValue" + } >= 0 } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/RestoreSlideToSeekBehaviorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/RestoreSlideToSeekBehaviorFingerprint.kt index e27dac2f0..a6904c670 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/RestoreSlideToSeekBehaviorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/RestoreSlideToSeekBehaviorFingerprint.kt @@ -5,6 +5,7 @@ import com.android.tools.smali.dexlib2.Opcode /** * This value restores the 'Slide to seek' behavior. + * Deprecated in YouTube v19.18.41+. */ internal object RestoreSlideToSeekBehaviorFingerprint : LiteralValueFingerprint( returnType = "Z", diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayFingerprint.kt index dd1fc9e7e..ad71e2e0d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayFingerprint.kt @@ -5,6 +5,7 @@ import com.android.tools.smali.dexlib2.Opcode /** * This value disables 'Playing at 2x speed' while holding down. + * Deprecated in YouTube v19.18.41+. */ internal object SpeedOverlayFingerprint : LiteralValueFingerprint( returnType = "Z", diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayValueFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayFloatValueFingerprint.kt similarity index 81% rename from src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayValueFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayFloatValueFingerprint.kt index c60dc03f8..d5557db6b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayValueFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayFloatValueFingerprint.kt @@ -7,8 +7,9 @@ import com.android.tools.smali.dexlib2.Opcode /** * This value is the key for the playback speed overlay value. + * Deprecated in YouTube v19.18.41+. */ -internal object SpeedOverlayValueFingerprint : LiteralValueFingerprint( +internal object SpeedOverlayFloatValueFingerprint : LiteralValueFingerprint( returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, opcodes = listOf(Opcode.DOUBLE_TO_FLOAT), diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayTextValueFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayTextValueFingerprint.kt index 434305547..53de379db 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayTextValueFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayTextValueFingerprint.kt @@ -1,14 +1,21 @@ package app.revanced.patches.youtube.player.speedoverlay.fingerprints import app.revanced.patcher.extensions.or -import app.revanced.util.fingerprint.ReferenceFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal object SpeedOverlayTextValueFingerprint : ReferenceFingerprint( +internal object SpeedOverlayTextValueFingerprint : MethodFingerprint( returnType = "V", accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL, parameters = emptyList(), opcodes = listOf(Opcode.CONST_WIDE_HIGH16), - reference = { "Ljava/math/BigDecimal;->signum()I" } + customFingerprint = { methodDef, _ -> + methodDef.indexOfFirstInstruction { + getReference()?.toString() == "Ljava/math/BigDecimal;->signum()I" + } >= 0 + } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsAnimationPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsAnimationPatch.kt index 153517b64..118a6eac0 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsAnimationPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsAnimationPatch.kt @@ -15,8 +15,8 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelF import app.revanced.patches.youtube.utils.settings.SettingsPatch.contexts import app.revanced.util.ResourceGroup import app.revanced.util.copyResources -import app.revanced.util.getWideLiteralInstructionIndex import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @@ -38,7 +38,7 @@ object ShortsAnimationPatch : BytecodePatch( ReelFeedbackPause to "setShortsPauseFeedback", ReelFeedbackPlay to "setShortsPlayFeedback", ).forEach { (literal, methodName) -> - val literalIndex = getWideLiteralInstructionIndex(literal) + val literalIndex = indexOfFirstWideLiteralInstructionValueOrThrow(literal) val viewIndex = indexOfFirstInstructionOrThrow(literalIndex) { opcode == Opcode.CHECK_CAST && (this as? ReferenceInstruction)?.reference?.toString() == LOTTIE_ANIMATION_VIEW_CLASS_DESCRIPTOR diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsComponentPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsComponentPatch.kt index a213ff0f0..e30dac5c8 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsComponentPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsComponentPatch.kt @@ -35,12 +35,12 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.Right import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.video.information.VideoInformationPatch import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.getTargetIndexWithReferenceOrThrow -import app.revanced.util.getWideLiteralInstructionIndex -import app.revanced.util.literalInstructionHook +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch +import app.revanced.util.replaceLiteralInstructionCall import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @@ -48,6 +48,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Suppress("unused") object ShortsComponentPatch : BaseBytecodePatch( @@ -106,10 +107,11 @@ object ShortsComponentPatch : BaseBytecodePatch( ShortsButtonFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(ReelRightDislikeIcon) + val constIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(ReelRightDislikeIcon) val constRegister = getInstruction(constIndex).registerA - val jumpIndex = getTargetIndexOrThrow(constIndex, Opcode.CONST_CLASS) + 2 + val jumpIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.CONST_CLASS) + 2 addInstructionsWithLabels( constIndex + 1, """ @@ -128,9 +130,9 @@ object ShortsComponentPatch : BaseBytecodePatch( ShortsButtonFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = getWideLiteralInstructionIndex(ReelRightLikeIcon) + val insertIndex = indexOfFirstWideLiteralInstructionValueOrThrow(ReelRightLikeIcon) val insertRegister = getInstruction(insertIndex).registerA - val jumpIndex = getTargetIndexOrThrow(insertIndex, Opcode.CONST_CLASS) + 2 + val jumpIndex = indexOfFirstInstructionOrThrow(insertIndex, Opcode.CONST_CLASS) + 2 addInstructionsWithLabels( insertIndex + 1, """ @@ -152,11 +154,12 @@ object ShortsComponentPatch : BaseBytecodePatch( if (shortsPivotLegacyFingerprintResult != null) { // Legacy method. shortsPivotLegacyFingerprintResult.mutableMethod.apply { - val targetIndex = getWideLiteralInstructionIndex(ReelForcedMuteButton) + val targetIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(ReelForcedMuteButton) val targetRegister = getInstruction(targetIndex).registerA - val insertIndex = getTargetIndexReversedOrThrow(targetIndex, Opcode.IF_EQZ) - val jumpIndex = getTargetIndexOrThrow(targetIndex, Opcode.GOTO) + val insertIndex = indexOfFirstInstructionReversedOrThrow(targetIndex, Opcode.IF_EQZ) + val jumpIndex = indexOfFirstInstructionOrThrow(targetIndex, Opcode.GOTO) addInstructionsWithLabels( insertIndex, """ @@ -173,7 +176,7 @@ object ShortsComponentPatch : BaseBytecodePatch( move-result v$REGISTER_TEMPLATE_REPLACEMENT """ - context.literalInstructionHook( + context.replaceLiteralInstructionCall( ReelPlayerRightPivotV2Size, smaliInstruction ) @@ -242,7 +245,8 @@ object ShortsComponentPatch : BaseBytecodePatch( lateinit var subscriptionFieldReference: FieldReference parentResult.mutableMethod.apply { - val targetIndex = getWideLiteralInstructionIndex(ReelPlayerFooter) - 1 + val targetIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(ReelPlayerFooter) - 1 subscriptionFieldReference = (getInstruction(targetIndex)).reference as FieldReference } @@ -297,9 +301,9 @@ object ShortsComponentPatch : BaseBytecodePatch( TextComponentSpecFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = - getTargetIndexWithReferenceOrThrow("Landroid/text/SpannableString;->valueOf(Ljava/lang/CharSequence;)Landroid/text/SpannableString;") - + val insertIndex = indexOfFirstInstructionOrThrow { + getReference()?.toString() == "Landroid/text/SpannableString;->valueOf(Ljava/lang/CharSequence;)Landroid/text/SpannableString;" + } val charSequenceRegister = getInstruction(insertIndex).registerC val conversionContextRegister = @@ -342,11 +346,11 @@ object ShortsComponentPatch : BaseBytecodePatch( ) { resultOrThrow().let { it.mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(id) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(id) val insertIndex = if (reversed) - getTargetIndexReversedOrThrow(constIndex, Opcode.CHECK_CAST) + indexOfFirstInstructionReversedOrThrow(constIndex, Opcode.CHECK_CAST) else - getTargetIndexOrThrow(constIndex, Opcode.CHECK_CAST) + indexOfFirstInstructionOrThrow(constIndex, Opcode.CHECK_CAST) val insertRegister = getInstruction(insertIndex).registerA addInstruction( @@ -363,8 +367,8 @@ object ShortsComponentPatch : BaseBytecodePatch( ) { resultOrThrow().let { it.mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(id) - val insertIndex = getTargetIndexOrThrow(constIndex, Opcode.CHECK_CAST) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(id) + val insertIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.CHECK_CAST) hideButtons(insertIndex, descriptor) } diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsNavigationBarPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsNavigationBarPatch.kt index 776dd3191..337a239fb 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsNavigationBarPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsNavigationBarPatch.kt @@ -1,67 +1,67 @@ package app.revanced.patches.youtube.shorts.components import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patches.youtube.shorts.components.fingerprints.BottomNavigationBarFingerprint -import app.revanced.patches.youtube.shorts.components.fingerprints.RenderBottomNavigationBarFingerprint -import app.revanced.patches.youtube.shorts.components.fingerprints.SetPivotBarFingerprint -import app.revanced.patches.youtube.utils.fingerprints.InitializeButtonsFingerprint +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patches.youtube.shorts.components.fingerprints.BottomBarContainerHeightFingerprint import app.revanced.patches.youtube.utils.integrations.Constants.SHORTS_CLASS_DESCRIPTOR -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getWalkerMethod +import app.revanced.patches.youtube.utils.navigation.NavigationBarHookPatch +import app.revanced.patches.youtube.utils.playertype.fingerprint.ReelWatchPagerFingerprint +import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.BottomBarContainer +import app.revanced.util.fingerprint.MultiMethodFingerprint +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValue +import app.revanced.util.patch.MultiMethodBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference -object ShortsNavigationBarPatch : BytecodePatch( - setOf( - BottomNavigationBarFingerprint, - InitializeButtonsFingerprint, - RenderBottomNavigationBarFingerprint - ) +/** + * Up to YouTube 19.28.42, there are two Methods with almost the same pattern. + * + * In certain YouTube versions, the hook should be done not on the first matching Method, but also on the last matching Method. + * + * 'Multiple fingerprint search' feature is not yet implemented in ReVanced Patcher, + * So I just implement it via [MultiMethodFingerprint]. + * + * Related Issues: + * https://github.com/ReVanced/revanced-patcher/issues/74 + * https://github.com/ReVanced/revanced-patcher/issues/308 + */ +@Patch(dependencies = [NavigationBarHookPatch::class]) +object ShortsNavigationBarPatch : MultiMethodBytecodePatch( + fingerprints = setOf(ReelWatchPagerFingerprint), + multiFingerprints = setOf(BottomBarContainerHeightFingerprint) ) { override fun execute(context: BytecodeContext) { + super.execute(context) - InitializeButtonsFingerprint.resultOrThrow().let { parentResult -> - SetPivotBarFingerprint.also { it.resolve(context, parentResult.classDef) } - .resultOrThrow().let { - it.mutableMethod.apply { - val startIndex = it.scanResult.patternScanResult!!.startIndex - val register = getInstruction(startIndex).registerA + // region patch for set navigation bar height. - addInstruction( - startIndex + 1, - "invoke-static {v$register}, $SHORTS_CLASS_DESCRIPTOR->setNavigationBar(Ljava/lang/Object;)V" - ) - } - } - } + BottomBarContainerHeightFingerprint.resultOrThrow().forEach { + it.mutableMethod.apply { + val constIndex = indexOfFirstWideLiteralInstructionValue(BottomBarContainer) - RenderBottomNavigationBarFingerprint.resultOrThrow().let { - val walkerMethod = - it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex) + val targetIndex = indexOfFirstInstructionOrThrow(constIndex) { + getReference()?.name == "getHeight" + } + 1 - walkerMethod.addInstruction( - 0, - "invoke-static {}, $SHORTS_CLASS_DESCRIPTOR->hideShortsNavigationBar()V" - ) - } - - BottomNavigationBarFingerprint.result?.let { - it.mutableMethod.apply { - val targetIndex = getTargetIndexWithMethodReferenceNameOrThrow("findViewById") + 1 - val insertRegister = getInstruction(targetIndex).registerA + val heightRegister = getInstruction(targetIndex).registerA addInstructions( targetIndex + 1, """ - invoke-static {v$insertRegister}, $SHORTS_CLASS_DESCRIPTOR->hideShortsNavigationBar(Landroid/view/View;)Landroid/view/View; - move-result-object v$insertRegister + invoke-static {v$heightRegister}, $SHORTS_CLASS_DESCRIPTOR->setNavigationBarHeight(I)I + move-result v$heightRegister """ ) } } + NavigationBarHookPatch.addBottomBarContainerHook("$SHORTS_CLASS_DESCRIPTOR->setNavigationBar(Landroid/view/View;)V") + + // endregion. + } } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsRepeatPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsRepeatPatch.kt index b7484a31c..8c16daabb 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsRepeatPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsRepeatPatch.kt @@ -9,14 +9,18 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.youtube.shorts.components.fingerprints.ReelEnumConstructorFingerprint import app.revanced.patches.youtube.shorts.components.fingerprints.ReelEnumStaticFingerprint import app.revanced.patches.youtube.utils.integrations.Constants.SHORTS_CLASS_DESCRIPTOR -import app.revanced.util.containsReferenceInstructionIndex import app.revanced.util.findMutableMethodOf -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndexOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference +import com.android.tools.smali.dexlib2.util.MethodUtil object ShortsRepeatPatch : BytecodePatch( setOf(ReelEnumConstructorFingerprint) @@ -36,16 +40,15 @@ object ShortsRepeatPatch : BytecodePatch( } val endScreenStringIndex = - getStringInstructionIndex("REEL_LOOP_BEHAVIOR_END_SCREEN") + indexOfFirstStringInstructionOrThrow("REEL_LOOP_BEHAVIOR_END_SCREEN") val endScreenReferenceIndex = - getTargetIndexOrThrow(endScreenStringIndex, Opcode.SPUT_OBJECT) + indexOfFirstInstructionOrThrow(endScreenStringIndex, Opcode.SPUT_OBJECT) val endScreenReference = getInstruction(endScreenReferenceIndex).reference.toString() - val enumMethodName = ReelEnumStaticFingerprint.resultOrThrow().mutableMethod.name - val enumMethodCall = "$definingClass->$enumMethodName(I)$definingClass" + val enumMethod = ReelEnumStaticFingerprint.resultOrThrow().mutableMethod - context.injectHook(endScreenReference, enumMethodCall) + context.injectHook(endScreenReference, enumMethod) } } } @@ -54,8 +57,8 @@ object ShortsRepeatPatch : BytecodePatch( enumName: String, fieldName: String ) { - val stringIndex = getStringInstructionIndex(enumName) - val insertIndex = getTargetIndexOrThrow(stringIndex, Opcode.SPUT_OBJECT) + val stringIndex = indexOfFirstStringInstructionOrThrow(enumName) + val insertIndex = indexOfFirstInstructionOrThrow(stringIndex, Opcode.SPUT_OBJECT) val insertRegister = getInstruction(insertIndex).registerA addInstruction( @@ -66,35 +69,41 @@ object ShortsRepeatPatch : BytecodePatch( private fun BytecodeContext.injectHook( endScreenReference: String, - enumMethodCall: String + enumMethod: MutableMethod ) { classes.forEach { classDef -> classDef.methods.filter { method -> method.parameters.size == 1 && method.parameters[0].startsWith("L") && method.returnType == "V" - && method.containsReferenceInstructionIndex(endScreenReference) + && method.indexOfFirstInstruction { + getReference()?.toString() == endScreenReference + } >= 0 }.forEach { targetMethod -> proxy(classDef) .mutableClass .findMutableMethodOf(targetMethod) .apply { - for ((index, instruction) in implementation!!.instructions.withIndex()) { - if (instruction.opcode != Opcode.INVOKE_STATIC) - continue - if ((instruction as ReferenceInstruction).reference.toString() != enumMethodCall) - continue + implementation!!.instructions + .withIndex() + .filter { (_, instruction) -> + val reference = (instruction as? ReferenceInstruction)?.reference + reference is MethodReference && + MethodUtil.methodSignaturesMatch(enumMethod, reference) + } + .map { (index, _) -> index } + .reversed() + .forEach { index -> + val register = + getInstruction(index + 1).registerA - val register = - getInstruction(index + 1).registerA - - addInstructions( - index + 2, """ - invoke-static {v$register}, $SHORTS_CLASS_DESCRIPTOR->changeShortsRepeatState(Ljava/lang/Enum;)Ljava/lang/Enum; - move-result-object v$register - """ - ) - } + addInstructions( + index + 2, """ + invoke-static {v$register}, $SHORTS_CLASS_DESCRIPTOR->changeShortsRepeatState(Ljava/lang/Enum;)Ljava/lang/Enum; + move-result-object v$register + """ + ) + } } } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsTimeStampPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsTimeStampPatch.kt index cf5371223..dfdc55a3f 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsTimeStampPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsTimeStampPatch.kt @@ -13,9 +13,9 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.MetaP import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelVodTimeStampsContainer import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT -import app.revanced.util.getWideLiteralInstructionIndex -import app.revanced.util.literalInstructionBooleanHook -import app.revanced.util.literalInstructionViewHook +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall +import app.revanced.util.injectLiteralInstructionViewCall import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @@ -38,14 +38,14 @@ object ShortsTimeStampPatch : BytecodePatch( ShortsTimeStampPrimaryFingerprint to 45638282, ShortsTimeStampSecondaryFingerprint to 45638187 ).forEach { (fingerprint, literal) -> - fingerprint.literalInstructionBooleanHook( + fingerprint.injectLiteralInstructionBooleanCall( literal, "$SHORTS_CLASS_DESCRIPTOR->enableShortsTimeStamp(Z)Z" ) } ShortsTimeStampPrimaryFingerprint.resultOrThrow().mutableMethod.apply { - val literalIndex = getWideLiteralInstructionIndex(10002) + val literalIndex = indexOfFirstWideLiteralInstructionValueOrThrow(10002) val literalRegister = getInstruction(literalIndex).registerA addInstructions( @@ -81,7 +81,7 @@ object ShortsTimeStampPatch : BytecodePatch( invoke-static {v$REGISTER_TEMPLATE_REPLACEMENT}, $SHORTS_CLASS_DESCRIPTOR->$methodName(Landroid/view/View;)V """ - fingerprint.literalInstructionViewHook(literalValue, smaliInstruction) + fingerprint.injectLiteralInstructionViewCall(literalValue, smaliInstruction) } // endregion diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/BottomBarContainerHeightFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/BottomBarContainerHeightFingerprint.kt new file mode 100644 index 000000000..776252b56 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/BottomBarContainerHeightFingerprint.kt @@ -0,0 +1,17 @@ +package app.revanced.patches.youtube.shorts.components.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.BottomBarContainer +import app.revanced.util.containsWideLiteralInstructionValue +import app.revanced.util.fingerprint.MultiMethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags + +internal object BottomBarContainerHeightFingerprint : MultiMethodFingerprint( + returnType = "V", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + parameters = listOf("Landroid/view/View;", "Landroid/os/Bundle;"), + strings = listOf("r_pfvc"), + customFingerprint = { methodDef, _ -> + methodDef.containsWideLiteralInstructionValue(BottomBarContainer) + }, +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/BottomNavigationBarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/BottomNavigationBarFingerprint.kt deleted file mode 100644 index c126985dc..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/BottomNavigationBarFingerprint.kt +++ /dev/null @@ -1,12 +0,0 @@ -package app.revanced.patches.youtube.shorts.components.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags - -internal object BottomNavigationBarFingerprint : MethodFingerprint( - returnType = "V", - accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, - parameters = listOf("Landroid/view/View;", "Landroid/os/Bundle;"), - strings = listOf("r_pfvc", "ReelWatchPaneFragmentViewModelKey") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ReelFeedbackFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ReelFeedbackFingerprint.kt index 901af28bd..5081b1ff5 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ReelFeedbackFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ReelFeedbackFingerprint.kt @@ -4,13 +4,13 @@ import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelFeedbackLike import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelFeedbackPause import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelFeedbackPlay -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue internal object ReelFeedbackFingerprint : MethodFingerprint( returnType = "V", customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(ReelFeedbackLike) - && methodDef.containsWideLiteralInstructionIndex(ReelFeedbackPause) - && methodDef.containsWideLiteralInstructionIndex(ReelFeedbackPlay) + methodDef.containsWideLiteralInstructionValue(ReelFeedbackLike) + && methodDef.containsWideLiteralInstructionValue(ReelFeedbackPause) + && methodDef.containsWideLiteralInstructionValue(ReelFeedbackPlay) }, ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/RenderBottomNavigationBarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/RenderBottomNavigationBarFingerprint.kt deleted file mode 100644 index 9dc16d62a..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/RenderBottomNavigationBarFingerprint.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.shorts.components.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.Opcode - -internal object RenderBottomNavigationBarFingerprint : MethodFingerprint( - returnType = "Landroid/view/View;", - opcodes = listOf( - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL - ), - strings = listOf("r_pfcv") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/SetPivotBarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/SetPivotBarFingerprint.kt deleted file mode 100644 index ac218b155..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/SetPivotBarFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.youtube.shorts.components.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode - -internal object SetPivotBarFingerprint : MethodFingerprint( - returnType = "V", - accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL, - parameters = listOf("Z"), - opcodes = listOf( - Opcode.CHECK_CAST, - Opcode.IF_EQZ - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsButtonFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsButtonFingerprint.kt index 6f7d94c0a..12e5e844c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsButtonFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsButtonFingerprint.kt @@ -6,15 +6,15 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelD import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelRightDislikeIcon import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelRightLikeIcon import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.RightComment -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue internal object ShortsButtonFingerprint : MethodFingerprint( returnType = "V", customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(ReelDynRemix) - && methodDef.containsWideLiteralInstructionIndex(ReelDynShare) - && methodDef.containsWideLiteralInstructionIndex(ReelRightDislikeIcon) - && methodDef.containsWideLiteralInstructionIndex(ReelRightLikeIcon) - && methodDef.containsWideLiteralInstructionIndex(RightComment) + methodDef.containsWideLiteralInstructionValue(ReelDynRemix) + && methodDef.containsWideLiteralInstructionValue(ReelDynShare) + && methodDef.containsWideLiteralInstructionValue(ReelRightDislikeIcon) + && methodDef.containsWideLiteralInstructionValue(ReelRightLikeIcon) + && methodDef.containsWideLiteralInstructionValue(RightComment) }, ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsTimeStampPrimaryFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsTimeStampPrimaryFingerprint.kt index 9e34f0119..d2a2fdfa0 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsTimeStampPrimaryFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsTimeStampPrimaryFingerprint.kt @@ -2,7 +2,7 @@ package app.revanced.patches.youtube.shorts.components.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object ShortsTimeStampPrimaryFingerprint : MethodFingerprint( @@ -10,8 +10,8 @@ internal object ShortsTimeStampPrimaryFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = listOf("I"), customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(45627350) - && methodDef.containsWideLiteralInstructionIndex(45638282) - && methodDef.containsWideLiteralInstructionIndex(10002) + methodDef.containsWideLiteralInstructionValue(45627350) + && methodDef.containsWideLiteralInstructionValue(45638282) + && methodDef.containsWideLiteralInstructionValue(10002) }, ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsToolBarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsToolBarFingerprint.kt index f0de713d8..2cae4bf8d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsToolBarFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsToolBarFingerprint.kt @@ -8,7 +8,9 @@ import com.android.tools.smali.dexlib2.Opcode internal object ShortsToolBarFingerprint : MethodFingerprint( returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, - parameters = listOf("Z", "L", "L"), opcodes = listOf(Opcode.IPUT_BOOLEAN), - strings = listOf("Null topBarButtons") + strings = listOf("Null topBarButtons"), + customFingerprint = { methodDef, _ -> + methodDef.parameterTypes.firstOrNull() == "Z" + } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/swipe/controls/SwipeControlsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/swipe/controls/SwipeControlsPatch.kt index 686c02dfc..1fcad075e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/swipe/controls/SwipeControlsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/swipe/controls/SwipeControlsPatch.kt @@ -23,8 +23,8 @@ import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch.contexts import app.revanced.util.ResourceGroup import app.revanced.util.copyResources -import app.revanced.util.getWideLiteralInstructionIndex -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import app.revanced.util.transformMethods @@ -90,7 +90,8 @@ object SwipeControlsPatch : BaseBytecodePatch( FullScreenEngagementOverlayFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val viewIndex = getWideLiteralInstructionIndex(FullScreenEngagementOverlay) + 3 + val viewIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(FullScreenEngagementOverlay) + 3 val viewRegister = getInstruction(viewIndex).registerA addInstruction( @@ -131,7 +132,7 @@ object SwipeControlsPatch : BaseBytecodePatch( // Since it does not support all versions, // add settings only if the patch is successful. SwipeToSwitchVideoFingerprint.result?.let { - SwipeToSwitchVideoFingerprint.literalInstructionBooleanHook( + SwipeToSwitchVideoFingerprint.injectLiteralInstructionBooleanCall( 45631116, "$INTEGRATIONS_SWIPE_CONTROLS_PATCH_CLASS_DESCRIPTOR->enableSwipeToSwitchVideo()Z" ) @@ -147,7 +148,7 @@ object SwipeControlsPatch : BaseBytecodePatch( // Since it does not support all versions, // add settings only if the patch is successful. WatchPanelGesturesFingerprint.result?.let { - WatchPanelGesturesFingerprint.literalInstructionBooleanHook( + WatchPanelGesturesFingerprint.injectLiteralInstructionBooleanCall( 45372793, "$INTEGRATIONS_SWIPE_CONTROLS_PATCH_CLASS_DESCRIPTOR->enableWatchPanelGestures()Z" ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/bottomsheet/BottomSheetHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/bottomsheet/BottomSheetHookPatch.kt new file mode 100644 index 000000000..52205105d --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/bottomsheet/BottomSheetHookPatch.kt @@ -0,0 +1,37 @@ +package app.revanced.patches.youtube.utils.bottomsheet + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patches.youtube.utils.bottomsheet.fingerprint.BottomSheetBehaviorFingerprint +import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH +import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch +import app.revanced.util.findMethodOrThrow +import app.revanced.util.resultOrThrow + +@Patch(dependencies = [SharedResourceIdPatch::class]) +object BottomSheetHookPatch : BytecodePatch( + setOf(BottomSheetBehaviorFingerprint) +) { + private const val INTEGRATIONS_BOTTOM_SHEET_HOOK_CLASS_DESCRIPTOR = + "$UTILS_PATH/BottomSheetHookPatch;" + + override fun execute(context: BytecodeContext) { + + val bottomSheetClass = + BottomSheetBehaviorFingerprint.resultOrThrow().mutableMethod.definingClass + + arrayOf( + "onAttachedToWindow", + "onDetachedFromWindow" + ).forEach { methodName -> + context.findMethodOrThrow(bottomSheetClass) { + name == methodName + }.addInstruction( + 1, + "invoke-static {}, $INTEGRATIONS_BOTTOM_SHEET_HOOK_CLASS_DESCRIPTOR->$methodName()V" + ) + } + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/bottomsheet/fingerprint/BottomSheetBehaviorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/bottomsheet/fingerprint/BottomSheetBehaviorFingerprint.kt new file mode 100644 index 000000000..73d6aa2cb --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/bottomsheet/fingerprint/BottomSheetBehaviorFingerprint.kt @@ -0,0 +1,9 @@ +package app.revanced.patches.youtube.utils.bottomsheet.fingerprint + +import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.DesignBottomSheet +import app.revanced.util.fingerprint.LiteralValueFingerprint + +internal object BottomSheetBehaviorFingerprint : LiteralValueFingerprint( + returnType = "V", + literalSupplier = { DesignBottomSheet } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/castbutton/CastButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/castbutton/CastButtonPatch.kt index 6db2ab6bb..01193f893 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/castbutton/CastButtonPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/castbutton/CastButtonPatch.kt @@ -6,7 +6,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.youtube.utils.castbutton.fingerprints.MenuItemInitializeFingerprint @@ -17,11 +16,15 @@ import app.revanced.patches.youtube.utils.integrations.Constants.PATCH_STATUS_CL import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.alsoResolve +import app.revanced.util.findMethodOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import app.revanced.util.updatePatchStatus import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Patch(dependencies = [SharedResourceIdPatch::class]) object CastButtonPatch : BytecodePatch( @@ -39,32 +42,30 @@ object CastButtonPatch : BytecodePatch( override fun execute(context: BytecodeContext) { - val toolbarMenuItemInitializeResult = MenuItemInitializeFingerprint.resultOrThrow() - MenuItemVisibilityFingerprint.resolve(context, toolbarMenuItemInitializeResult.classDef) - - toolbarMenuItemInitializeMethod = toolbarMenuItemInitializeResult.mutableMethod - toolbarMenuItemVisibilityMethod = - MenuItemVisibilityFingerprint.resultOrThrow().mutableMethod + toolbarMenuItemInitializeMethod = MenuItemInitializeFingerprint.resultOrThrow() + .mutableMethod + toolbarMenuItemVisibilityMethod = MenuItemVisibilityFingerprint.alsoResolve( + context, MenuItemInitializeFingerprint + ).mutableMethod playerButtonMethod = PlayerButtonFingerprint.resultOrThrow().mutableMethod - val buttonClass = context.findClass("MediaRouteButton") - ?: throw PatchException("MediaRouteButton class not found.") - - buttonClass.mutableClass.methods.find { it.name == "setVisibility" }?.apply { - addInstructions( - 0, """ - invoke-static {p1}, $INTEGRATIONS_CLASS_DESCRIPTOR->hideCastButton(I)I - move-result p1 - """ - ) - } ?: throw PatchException("setVisibility method not found.") + context.findMethodOrThrow("Landroidx/mediarouter/app/MediaRouteButton;") { + name == "setVisibility" + }.addInstructions( + 0, """ + invoke-static {p1}, $INTEGRATIONS_CLASS_DESCRIPTOR->hideCastButton(I)I + move-result p1 + """ + ) } internal fun hookPlayerButton(context: BytecodeContext) { playerButtonMethod.apply { - val index = getTargetIndexWithMethodReferenceNameOrThrow("setVisibility") + val index = indexOfFirstInstructionOrThrow { + getReference()?.name == "setVisibility" + } val instruction = getInstruction(index) val viewRegister = instruction.registerC val visibilityRegister = instruction.registerD @@ -84,8 +85,9 @@ object CastButtonPatch : BytecodePatch( internal fun hookToolBarButton(context: BytecodeContext) { toolbarMenuItemInitializeMethod.apply { - val index = getTargetIndexWithMethodReferenceNameOrThrow("setShowAsAction") + 1 - + val index = indexOfFirstInstructionOrThrow { + getReference()?.name == "setShowAsAction" + } + 1 addInstruction( index, "invoke-static {p1}, $GENERAL_CLASS_DESCRIPTOR->hideCastButton(Landroid/view/MenuItem;)V" diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/castbutton/fingerprints/MenuItemVisibilityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/castbutton/fingerprints/MenuItemVisibilityFingerprint.kt index 18e37f62c..a52f69071 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/castbutton/fingerprints/MenuItemVisibilityFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/castbutton/fingerprints/MenuItemVisibilityFingerprint.kt @@ -1,12 +1,19 @@ package app.revanced.patches.youtube.utils.castbutton.fingerprints import app.revanced.patcher.extensions.or -import app.revanced.util.fingerprint.MethodReferenceNameFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal object MenuItemVisibilityFingerprint : MethodReferenceNameFingerprint( +internal object MenuItemVisibilityFingerprint : MethodFingerprint( returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = listOf("Z"), - reference = { "setVisible" } + customFingerprint = { methodDef, _ -> + methodDef.indexOfFirstInstruction { + getReference()?.name == "setVisible" + } >= 0 + } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/EngagementPanelControllerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/EngagementPanelBuilderFingerprint.kt similarity index 79% rename from src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/EngagementPanelControllerFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/EngagementPanelBuilderFingerprint.kt index ffc7e9c97..45002b73e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/EngagementPanelControllerFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/EngagementPanelBuilderFingerprint.kt @@ -1,10 +1,10 @@ -package app.revanced.patches.youtube.player.components.fingerprints +package app.revanced.patches.youtube.utils.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import com.android.tools.smali.dexlib2.AccessFlags -internal object EngagementPanelControllerFingerprint : MethodFingerprint( +internal object EngagementPanelBuilderFingerprint : MethodFingerprint( returnType = "L", accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL, parameters = listOf("L", "L", "Z", "Z"), diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/PlayerSeekbarColorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/PlayerSeekbarColorFingerprint.kt index e14a7ad92..20063ed0e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/PlayerSeekbarColorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/PlayerSeekbarColorFingerprint.kt @@ -4,15 +4,15 @@ import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.InlineTimeBarColorizedBarPlayedColorDark import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.InlineTimeBarPlayedNotHighlightedColor -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object PlayerSeekbarColorFingerprint : MethodFingerprint( returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(InlineTimeBarColorizedBarPlayedColorDark) - && methodDef.containsWideLiteralInstructionIndex( + methodDef.containsWideLiteralInstructionValue(InlineTimeBarColorizedBarPlayedColorDark) + && methodDef.containsWideLiteralInstructionValue( InlineTimeBarPlayedNotHighlightedColor ) } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/YouTubeControlsOverlayFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/YouTubeControlsOverlayFingerprint.kt index 727b29ced..39a48fb61 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/YouTubeControlsOverlayFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/YouTubeControlsOverlayFingerprint.kt @@ -8,7 +8,7 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.Inset import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ScrimOverlay import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.SeekUndoEduOverlayStub import app.revanced.patches.youtube.utils.sponsorblock.SponsorBlockBytecodePatch -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode @@ -26,9 +26,9 @@ internal object YouTubeControlsOverlayFingerprint : MethodFingerprint( accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL, parameters = emptyList(), customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(FadeDurationFast) - && methodDef.containsWideLiteralInstructionIndex(InsetOverlayViewLayout) - && methodDef.containsWideLiteralInstructionIndex(ScrimOverlay) - && methodDef.containsWideLiteralInstructionIndex(SeekUndoEduOverlayStub) + methodDef.containsWideLiteralInstructionValue(FadeDurationFast) + && methodDef.containsWideLiteralInstructionValue(InsetOverlayViewLayout) + && methodDef.containsWideLiteralInstructionValue(ScrimOverlay) + && methodDef.containsWideLiteralInstructionValue(SeekUndoEduOverlayStub) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/bottomui/CfBottomUIPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/bottomui/CfBottomUIPatch.kt index 2ee24f0a1..66374cddf 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/bottomui/CfBottomUIPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/bottomui/CfBottomUIPatch.kt @@ -1,16 +1,11 @@ package app.revanced.patches.youtube.utils.fix.bottomui import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.youtube.utils.fix.bottomui.fingerprints.FullscreenButtonPositionFingerprint import app.revanced.patches.youtube.utils.fix.bottomui.fingerprints.FullscreenButtonViewStubFingerprint -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getWideLiteralInstructionIndex -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import app.revanced.util.injectLiteralInstructionBooleanCall @Patch( description = "Fixes an issue where overlay button patches were broken by the new layout." @@ -32,19 +27,10 @@ object CfBottomUIPatch : BytecodePatch( FullscreenButtonPositionFingerprint to 45627640 ).forEach { (fingerprint, literalValue) -> fingerprint.result?.let { - it.mutableMethod.apply { - val targetIndex = getTargetIndexOrThrow( - getWideLiteralInstructionIndex(literalValue.toLong()), - Opcode.MOVE_RESULT - ) - val targetRegister = - getInstruction(targetIndex).registerA - - addInstruction( - targetIndex + 1, - "const/4 v$targetRegister, 0x0" - ) - } + fingerprint.injectLiteralInstructionBooleanCall( + literalValue, + "0x0" + ) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/cairo/CairoSettingsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/cairo/CairoSettingsPatch.kt index 74b3ee248..c20fd4a11 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/cairo/CairoSettingsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/cairo/CairoSettingsPatch.kt @@ -1,16 +1,11 @@ package app.revanced.patches.youtube.utils.fix.cairo import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.youtube.misc.backgroundplayback.BackgroundPlaybackPatch import app.revanced.patches.youtube.utils.fix.cairo.fingerprints.CarioFragmentConfigFingerprint -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getWideLiteralInstructionIndex -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import app.revanced.util.injectLiteralInstructionBooleanCall @Patch( description = "Fixes issues where Cairo Fragment is applied." @@ -31,19 +26,10 @@ object CairoSettingsPatch : BytecodePatch( * for screenshots of the Cairo Fragment. */ CarioFragmentConfigFingerprint.result?.let { - it.mutableMethod.apply { - val targetIndex = - getTargetIndexOrThrow( - getWideLiteralInstructionIndex(45532100), - Opcode.MOVE_RESULT - ) - val targetRegister = getInstruction(targetIndex).registerA - - addInstruction( - targetIndex + 1, - "const/4 v$targetRegister, 0x0" - ) - } + CarioFragmentConfigFingerprint.injectLiteralInstructionBooleanCall( + 45532100, + "0x0" + ) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/shortsplayback/ShortsPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/shortsplayback/ShortsPlaybackPatch.kt index 60da209b9..9788f3bec 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/shortsplayback/ShortsPlaybackPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/shortsplayback/ShortsPlaybackPatch.kt @@ -1,15 +1,10 @@ package app.revanced.patches.youtube.utils.fix.shortsplayback import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.youtube.utils.fix.shortsplayback.fingerprints.ShortsPlaybackFingerprint -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getWideLiteralInstructionIndex -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import app.revanced.util.injectLiteralInstructionBooleanCall @Patch( description = "Fix issue with looping at the start of the video when applying default video quality to Shorts." @@ -26,19 +21,10 @@ object ShortsPlaybackPatch : BytecodePatch( * RVX applies default video quality to Shorts as well, so this patch is required. */ ShortsPlaybackFingerprint.result?.let { - it.mutableMethod.apply { - val targetIndex = - getTargetIndexOrThrow( - getWideLiteralInstructionIndex(45387052), - Opcode.MOVE_RESULT - ) - val targetRegister = getInstruction(targetIndex).registerA - - addInstruction( - targetIndex + 1, - "const/4 v$targetRegister, 0x0" - ) - } + ShortsPlaybackFingerprint.injectLiteralInstructionBooleanCall( + 45387052, + "0x0" + ) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/suggestedvideoendscreen/SuggestedVideoEndScreenPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/suggestedvideoendscreen/SuggestedVideoEndScreenPatch.kt index 702185779..a4b297c0b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/suggestedvideoendscreen/SuggestedVideoEndScreenPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/suggestedvideoendscreen/SuggestedVideoEndScreenPatch.kt @@ -8,9 +8,9 @@ import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.youtube.utils.fix.suggestedvideoendscreen.fingerprints.RemoveOnLayoutChangeListenerFingerprint import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow import app.revanced.util.getWalkerMethod +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction @@ -36,9 +36,10 @@ object SuggestedVideoEndScreenPatch : BytecodePatch( it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex) walkerIndex.apply { - val invokeInterfaceIndex = getTargetIndexOrThrow(Opcode.INVOKE_INTERFACE) + val invokeInterfaceIndex = + indexOfFirstInstructionOrThrow(opcode = Opcode.INVOKE_INTERFACE) val iGetObjectIndex = - getTargetIndexReversedOrThrow(invokeInterfaceIndex, Opcode.IGET_OBJECT) + indexOfFirstInstructionReversedOrThrow(invokeInterfaceIndex, Opcode.IGET_OBJECT) val invokeInterfaceReference = getInstruction(invokeInterfaceIndex).reference diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/suggestedvideoendscreen/fingerprints/RemoveOnLayoutChangeListenerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/suggestedvideoendscreen/fingerprints/RemoveOnLayoutChangeListenerFingerprint.kt index 2c0f744e7..2c923219b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/suggestedvideoendscreen/fingerprints/RemoveOnLayoutChangeListenerFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/suggestedvideoendscreen/fingerprints/RemoveOnLayoutChangeListenerFingerprint.kt @@ -1,15 +1,18 @@ package app.revanced.patches.youtube.utils.fix.suggestedvideoendscreen.fingerprints import app.revanced.patcher.extensions.or -import app.revanced.util.fingerprint.ReferenceFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.reference.MethodReference /** * This fingerprint is also compatible with very old YouTube versions. - * Tested on YouTube v16.40.36, v18.29.38, v19.12.41. + * Tested on YouTube v16.40.36, v18.29.38, v19.16.39. */ -internal object RemoveOnLayoutChangeListenerFingerprint : ReferenceFingerprint( +internal object RemoveOnLayoutChangeListenerFingerprint : MethodFingerprint( returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = emptyList(), @@ -18,5 +21,10 @@ internal object RemoveOnLayoutChangeListenerFingerprint : ReferenceFingerprint( Opcode.INVOKE_VIRTUAL ), // This is the only reference present in the entire smali. - reference = { "YouTubePlayerOverlaysLayout;->removeOnLayoutChangeListener(Landroid/view/View${'$'}OnLayoutChangeListener;)V" } + customFingerprint = { methodDef, _ -> + methodDef.indexOfFirstInstruction { + getReference()?.toString() + ?.endsWith("YouTubePlayerOverlaysLayout;->removeOnLayoutChangeListener(Landroid/view/View${'$'}OnLayoutChangeListener;)V") == true + } >= 0 + } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/flyoutmenu/FlyoutMenuHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/flyoutmenu/FlyoutMenuHookPatch.kt index 56270f123..f6275602a 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/flyoutmenu/FlyoutMenuHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/flyoutmenu/FlyoutMenuHookPatch.kt @@ -7,7 +7,7 @@ import app.revanced.patches.youtube.utils.fingerprints.PlaybackRateBottomSheetBu import app.revanced.patches.youtube.utils.flyoutmenu.fingerprints.VideoQualityBottomSheetClassFingerprint import app.revanced.patches.youtube.utils.integrations.Constants.INTEGRATIONS_PATH import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch -import app.revanced.util.addFieldAndInstructions +import app.revanced.util.addStaticFieldToIntegration import app.revanced.util.resultOrThrow @Patch( @@ -25,10 +25,6 @@ object FlyoutMenuHookPatch : BytecodePatch( override fun execute(context: BytecodeContext) { - val videoUtilsMutableClass = context.findClass( - INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR - )!!.mutableClass - PlaybackRateBottomSheetBuilderFingerprint.resultOrThrow().let { it.mutableMethod.apply { val smaliInstructions = @@ -39,13 +35,12 @@ object FlyoutMenuHookPatch : BytecodePatch( return-void """ - videoUtilsMutableClass.addFieldAndInstructions( - context, + context.addStaticFieldToIntegration( + INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR, "showPlaybackSpeedFlyoutMenu", "playbackRateBottomSheetClass", definingClass, - smaliInstructions, - true + smaliInstructions ) } } @@ -61,13 +56,12 @@ object FlyoutMenuHookPatch : BytecodePatch( return-void """ - videoUtilsMutableClass.addFieldAndInstructions( - context, + context.addStaticFieldToIntegration( + INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR, "showVideoQualityFlyoutMenu", "videoQualityBottomSheetClass", definingClass, - smaliInstructions, - true + smaliInstructions ) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/integrations/fingerprints/StandalonePlayerActivityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/integrations/fingerprints/StandalonePlayerActivityFingerprint.kt index 2b643e64f..d42bea6d9 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/integrations/fingerprints/StandalonePlayerActivityFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/integrations/fingerprints/StandalonePlayerActivityFingerprint.kt @@ -8,7 +8,10 @@ import app.revanced.patches.shared.integrations.BaseIntegrationsPatch.Integratio * In 2023 supported was ended and is no longer available, * but this may still be used by older apps: * https://developers.google.com/youtube/android/player + * + * Deprecated in YouTube v19.38.xx+. */ +@Deprecated("Fingerprint is obsolete and will be deleted soon") internal object StandalonePlayerActivityFingerprint : IntegrationsFingerprint( customFingerprint = { methodDef, _ -> methodDef.definingClass == "Lcom/google/android/youtube/api/StandalonePlayerActivity;" diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/lottie/LottieAnimationViewHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/lottie/LottieAnimationViewHookPatch.kt index 24e436f45..1d3e106f4 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/lottie/LottieAnimationViewHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/lottie/LottieAnimationViewHookPatch.kt @@ -3,11 +3,11 @@ package app.revanced.patches.youtube.utils.lottie import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH import app.revanced.patches.youtube.utils.lottie.fingerprints.SetAnimationFingerprint import app.revanced.patches.youtube.utils.lottie.fingerprints.SetAnimationFingerprint.LOTTIE_ANIMATION_VIEW_CLASS_DESCRIPTOR +import app.revanced.util.findMethodOrThrow import app.revanced.util.resultOrThrow @Patch( @@ -20,21 +20,15 @@ object LottieAnimationViewHookPatch : BytecodePatch( "$UTILS_PATH/LottieAnimationViewPatch;" override fun execute(context: BytecodeContext) { - - val setAnimationMethodName = SetAnimationFingerprint.resultOrThrow().mutableMethod.name - val setAnimationCall = "invoke-virtual {p0, p1}, " + - LOTTIE_ANIMATION_VIEW_CLASS_DESCRIPTOR + - "->" + - setAnimationMethodName + - "(I)V" - - context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR) - ?.mutableClass - ?.methods - ?.first { method -> method.name == "setAnimation" } - ?.addInstruction( - 0, - setAnimationCall - ) ?: throw PatchException("Could not find setAnimation method") + context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) { + name == "setAnimation" + }.addInstruction( + 0, + "invoke-virtual {p0, p1}, " + + LOTTIE_ANIMATION_VIEW_CLASS_DESCRIPTOR + + "->" + + SetAnimationFingerprint.resultOrThrow().mutableMethod.name + + "(I)V" + ) } } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/NavigationBarHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/NavigationBarHookPatch.kt index 92b600ca5..65d8819e7 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/NavigationBarHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/NavigationBarHookPatch.kt @@ -2,25 +2,24 @@ package app.revanced.patches.youtube.utils.navigation import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstructions import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.youtube.utils.fingerprints.InitializeButtonsFingerprint import app.revanced.patches.youtube.utils.integrations.Constants.SHARED_PATH import app.revanced.patches.youtube.utils.mainactivity.MainActivityResolvePatch -import app.revanced.patches.youtube.utils.navigation.fingerprints.MobileTopBarButtonOnClickFingerprint +import app.revanced.patches.youtube.utils.navigation.fingerprints.InitializeBottomBarContainerFingerprint +import app.revanced.patches.youtube.utils.navigation.fingerprints.InitializeButtonsFingerprint import app.revanced.patches.youtube.utils.navigation.fingerprints.NavigationEnumFingerprint import app.revanced.patches.youtube.utils.navigation.fingerprints.PivotBarButtonsCreateDrawableViewFingerprint import app.revanced.patches.youtube.utils.navigation.fingerprints.PivotBarButtonsCreateResourceViewFingerprint import app.revanced.patches.youtube.utils.navigation.fingerprints.PivotBarButtonsViewSetSelectedFingerprint import app.revanced.patches.youtube.utils.navigation.fingerprints.PivotBarConstructorFingerprint -import app.revanced.patches.youtube.utils.navigation.fingerprints.SettingsActivityOnBackPressedFingerprint import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch +import app.revanced.util.findMethodOrThrow import app.revanced.util.getReference import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -41,13 +40,12 @@ import com.android.tools.smali.dexlib2.util.MethodUtil @Suppress("unused") object NavigationBarHookPatch : BytecodePatch( setOf( - MobileTopBarButtonOnClickFingerprint, + InitializeBottomBarContainerFingerprint, NavigationEnumFingerprint, PivotBarButtonsCreateDrawableViewFingerprint, PivotBarButtonsCreateResourceViewFingerprint, PivotBarButtonsViewSetSelectedFingerprint, PivotBarConstructorFingerprint, - SettingsActivityOnBackPressedFingerprint ), ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = @@ -57,6 +55,10 @@ object NavigationBarHookPatch : BytecodePatch( private lateinit var navigationTabCreatedCallback: MutableMethod + private lateinit var bottomBarContainerMethod: MutableMethod + private var bottomBarContainerIndex = 0 + private var bottomBarContainerRegister = 0 + override fun execute(context: BytecodeContext) { fun MutableMethod.addHook(hook: Hook, insertPredicate: Instruction.() -> Boolean) { val filtered = getInstructions().filter(insertPredicate) @@ -110,43 +112,31 @@ object NavigationBarHookPatch : BytecodePatch( val instruction = getInstruction(index) val viewRegister = instruction.registerC val isSelectedRegister = instruction.registerD - val freeRegister = implementation!!.registerCount - parameters.size - 2 addInstruction( index + 1, - "invoke-static { v$viewRegister, v$freeRegister, v$isSelectedRegister }, " + - "$INTEGRATIONS_CLASS_DESCRIPTOR->navigationTabSelected(Landroid/view/View;IZ)V", - ) - addInstruction( - 0, - "move/16 v$freeRegister, p1" + "invoke-static { v$viewRegister, v$isSelectedRegister }, " + + "$INTEGRATIONS_CLASS_DESCRIPTOR->navigationTabSelected(Landroid/view/View;Z)V", ) } } navigationTabCreatedCallback = - context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)?.mutableClass?.methods?.first { method -> - method.name == "navigationTabCreatedCallback" - } ?: throw PatchException("Could not find navigationTabCreatedCallback method") + context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) { + name == "navigationTabCreatedCallback" + } MainActivityResolvePatch.injectOnBackPressedMethodCall( INTEGRATIONS_CLASS_DESCRIPTOR, "onBackPressed" ) - /** - * Since it is used only after opening the library tab, set index to 3. - */ - arrayOf( - MobileTopBarButtonOnClickFingerprint, - SettingsActivityOnBackPressedFingerprint - ).forEach { fingerprint -> - fingerprint.resultOrThrow().mutableMethod.addInstructions( - 0, """ - const/4 v0, 0x3 - invoke-static {v0}, $INTEGRATIONS_CLASS_DESCRIPTOR->setNavigationTabIndex(I)V - """ - ) + InitializeBottomBarContainerFingerprint.resultOrThrow().mutableMethod.apply { + bottomBarContainerMethod = this + bottomBarContainerIndex = + InitializeBottomBarContainerFingerprint.indexOfLayoutChangeListenerInstruction(this) + bottomBarContainerRegister = + getInstruction(bottomBarContainerIndex).registerC } } @@ -162,6 +152,12 @@ object NavigationBarHookPatch : BytecodePatch( } } + fun addBottomBarContainerHook(descriptor: String) = + bottomBarContainerMethod.addInstruction( + bottomBarContainerIndex, + "invoke-static { v$bottomBarContainerRegister }, $descriptor" + ) + private enum class Hook(val methodName: String, val parameters: String) { SET_LAST_APP_NAVIGATION_ENUM("setLastAppNavigationEnum", "Ljava/lang/Enum;"), NAVIGATION_TAB_LOADED("navigationTabLoaded", "Landroid/view/View;"), diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/fingerprints/InitializeBottomBarContainerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/fingerprints/InitializeBottomBarContainerFingerprint.kt new file mode 100644 index 000000000..9991cae7d --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/fingerprints/InitializeBottomBarContainerFingerprint.kt @@ -0,0 +1,29 @@ +package app.revanced.patches.youtube.utils.navigation.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.youtube.utils.navigation.fingerprints.InitializeBottomBarContainerFingerprint.indexOfLayoutChangeListenerInstruction +import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.BottomBarContainer +import app.revanced.util.containsWideLiteralInstructionValue +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.MethodReference + +internal object InitializeBottomBarContainerFingerprint : MethodFingerprint( + returnType = "V", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + customFingerprint = { methodDef, classDef -> + AccessFlags.SYNTHETIC.isSet(classDef.accessFlags) && + methodDef.containsWideLiteralInstructionValue(BottomBarContainer) && + indexOfLayoutChangeListenerInstruction(methodDef) >= 0 + }, +) { + fun indexOfLayoutChangeListenerInstruction(methodDef: Method) = + methodDef.indexOfFirstInstruction { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.toString() == "Landroid/view/View;->addOnLayoutChangeListener(Landroid/view/View${'$'}OnLayoutChangeListener;)V" + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/InitializeButtonsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/fingerprints/InitializeButtonsFingerprint.kt similarity index 86% rename from src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/InitializeButtonsFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/utils/navigation/fingerprints/InitializeButtonsFingerprint.kt index 0b054f08d..98d93cf68 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/InitializeButtonsFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/fingerprints/InitializeButtonsFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.youtube.utils.fingerprints +package app.revanced.patches.youtube.utils.navigation.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ImageOnlyTab diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/fingerprints/MobileTopBarButtonOnClickFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/fingerprints/MobileTopBarButtonOnClickFingerprint.kt deleted file mode 100644 index 48215f9c8..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/fingerprints/MobileTopBarButtonOnClickFingerprint.kt +++ /dev/null @@ -1,8 +0,0 @@ -package app.revanced.patches.youtube.utils.navigation.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint - -object MobileTopBarButtonOnClickFingerprint : MethodFingerprint( - strings = listOf("MenuButtonRendererKey"), - customFingerprint = { methodDef, _ -> methodDef.name == "onClick" } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/fingerprints/SettingsActivityOnBackPressedFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/fingerprints/SettingsActivityOnBackPressedFingerprint.kt deleted file mode 100644 index 03fe1c87c..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/fingerprints/SettingsActivityOnBackPressedFingerprint.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.youtube.utils.navigation.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags - -object SettingsActivityOnBackPressedFingerprint : MethodFingerprint( - accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, - returnType = "V", - customFingerprint = { methodDef, _ -> - methodDef.definingClass.endsWith("/SettingsActivity;") - && methodDef.name == "onBackPressed" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsPatch.kt index 324b69131..03f5c5ca2 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsPatch.kt @@ -16,8 +16,9 @@ import app.revanced.patches.youtube.utils.playercontrols.fingerprints.MotionEven import app.revanced.patches.youtube.utils.playercontrols.fingerprints.PlayerControlsVisibilityEntityModelFingerprint import app.revanced.patches.youtube.utils.playercontrols.fingerprints.PlayerControlsVisibilityFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.alsoResolve +import app.revanced.util.findMethodOrThrow +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @@ -50,13 +51,11 @@ object PlayerControlsPatch : BytecodePatch( // region patch for hook visibility of play control buttons (e.g. pause, play button, etc) - PlayerButtonsVisibilityFingerprint.resolve( - context, - PlayerButtonsResourcesFingerprint.resultOrThrow().mutableClass - ) - PlayerButtonsVisibilityFingerprint.resultOrThrow().let { + PlayerButtonsVisibilityFingerprint.alsoResolve( + context, PlayerButtonsResourcesFingerprint + ).let { it.mutableMethod.apply { - val viewIndex = getTargetIndexOrThrow(Opcode.INVOKE_INTERFACE) + val viewIndex = indexOfFirstInstructionOrThrow(opcode = Opcode.INVOKE_INTERFACE) val viewRegister = getInstruction(viewIndex).registerD addInstruction( @@ -70,11 +69,9 @@ object PlayerControlsPatch : BytecodePatch( // region patch for hook visibility of play controls layout - PlayerControlsVisibilityFingerprint.resolve( - context, - YouTubeControlsOverlayFingerprint.resultOrThrow().mutableClass - ) - PlayerControlsVisibilityFingerprint.resultOrThrow().mutableMethod.addInstruction( + PlayerControlsVisibilityFingerprint.alsoResolve( + context, YouTubeControlsOverlayFingerprint + ).mutableMethod.addInstruction( 0, "invoke-static {p1}, $INTEGRATIONS_CLASS_DESCRIPTOR->changeVisibility(Z)V" ) @@ -83,12 +80,10 @@ object PlayerControlsPatch : BytecodePatch( // region patch for detecting motion events in play controls layout - MotionEventFingerprint.resolve( - context, - YouTubeControlsOverlayFingerprint.resultOrThrow().mutableClass - ) - MotionEventFingerprint.resultOrThrow().mutableMethod.apply { - val insertIndex = getTargetIndexWithMethodReferenceNameOrThrow("setTranslationY") + 1 + MotionEventFingerprint.alsoResolve( + context, YouTubeControlsOverlayFingerprint + ).mutableMethod.apply { + val insertIndex = MotionEventFingerprint.indexOfTranslationInstruction(this) + 1 addInstruction( insertIndex, @@ -121,28 +116,25 @@ object PlayerControlsPatch : BytecodePatch( // region set methods to inject into integration - val playerControlsMutableClass = - context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass - changeVisibilityMethod = - playerControlsMutableClass.methods.single { method -> - method.name == "changeVisibility" - && method.parameters == listOf("Z", "Z") + context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) { + name == "changeVisibility" + && parameters == listOf("Z", "Z") } changeVisibilityNegatedImmediatelyMethod = - playerControlsMutableClass.methods.single { method -> - method.name == "changeVisibilityNegatedImmediately" + context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) { + name == "changeVisibilityNegatedImmediately" } initializeBottomControlButtonMethod = - playerControlsMutableClass.methods.single { method -> - method.name == "initializeBottomControlButton" + context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) { + name == "initializeBottomControlButton" } initializeTopControlButtonMethod = - playerControlsMutableClass.methods.single { method -> - method.name == "initializeTopControlButton" + context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) { + name == "initializeTopControlButton" } // endregion diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsVisibilityHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsVisibilityHookPatch.kt index b991ec65c..5f9fd61ff 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsVisibilityHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsVisibilityHookPatch.kt @@ -9,7 +9,7 @@ import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH import app.revanced.patches.youtube.utils.playercontrols.fingerprints.PlayerControlsVisibilityEntityModelFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch -import app.revanced.util.getTargetIndexOrThrow +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction @@ -31,7 +31,7 @@ object PlayerControlsVisibilityHookPatch : BytecodePatch( val staticReference = getInstruction(startIndex + 1).reference it.mutableClass.methods.find { method -> method.name == "" }?.apply { - val targetIndex = getTargetIndexOrThrow(Opcode.IPUT_OBJECT) + val targetIndex = indexOfFirstInstructionOrThrow(Opcode.IPUT_OBJECT) val targetRegister = getInstruction(targetIndex).registerA diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/fingerprints/MotionEventFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/fingerprints/MotionEventFingerprint.kt index 45d9d329d..743129ab4 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/fingerprints/MotionEventFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/fingerprints/MotionEventFingerprint.kt @@ -1,9 +1,21 @@ package app.revanced.patches.youtube.utils.playercontrols.fingerprints -import app.revanced.util.fingerprint.MethodReferenceNameFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.youtube.utils.playercontrols.fingerprints.MotionEventFingerprint.indexOfTranslationInstruction +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionReversed +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal object MotionEventFingerprint : MethodReferenceNameFingerprint( +internal object MotionEventFingerprint : MethodFingerprint( returnType = "V", parameters = listOf("Landroid/view/MotionEvent;"), - reference = { "setTranslationY" } -) + customFingerprint = { methodDef, _ -> + indexOfTranslationInstruction(methodDef) >= 0 + } +) { + fun indexOfTranslationInstruction(methodDef: Method) = + methodDef.indexOfFirstInstructionReversed { + getReference()?.name == "setTranslationY" + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/PlayerTypeHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/PlayerTypeHookPatch.kt index 9f208cdfe..748a0f96d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/PlayerTypeHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/PlayerTypeHookPatch.kt @@ -13,14 +13,21 @@ import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH import app.revanced.patches.youtube.utils.playertype.fingerprint.ActionBarSearchResultsFingerprint import app.revanced.patches.youtube.utils.playertype.fingerprint.BrowseIdClassFingerprint import app.revanced.patches.youtube.utils.playertype.fingerprint.PlayerTypeFingerprint +import app.revanced.patches.youtube.utils.playertype.fingerprint.ReelWatchPagerFingerprint import app.revanced.patches.youtube.utils.playertype.fingerprint.VideoStateFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch -import app.revanced.util.addFieldAndInstructions -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndexOrThrow +import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelWatchPlayer +import app.revanced.util.addStaticFieldToIntegration +import app.revanced.util.alsoResolve +import app.revanced.util.findMethodOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode 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.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.reference.FieldReference @@ -30,6 +37,7 @@ object PlayerTypeHookPatch : BytecodePatch( ActionBarSearchResultsFingerprint, BrowseIdClassFingerprint, PlayerTypeFingerprint, + ReelWatchPagerFingerprint, YouTubeControlsOverlayFingerprint ) ) { @@ -43,36 +51,48 @@ object PlayerTypeHookPatch : BytecodePatch( // region patch for set player type - PlayerTypeFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - addInstruction( - 0, - "invoke-static {p1}, " + - "$INTEGRATIONS_PLAYER_TYPE_HOOK_CLASS_DESCRIPTOR->setPlayerType(Ljava/lang/Enum;)V" - ) + PlayerTypeFingerprint.resultOrThrow().mutableMethod.addInstruction( + 0, + "invoke-static {p1}, " + + "$INTEGRATIONS_PLAYER_TYPE_HOOK_CLASS_DESCRIPTOR->setPlayerType(Ljava/lang/Enum;)V" + ) + + // endregion + + // region patch for set shorts player state + + ReelWatchPagerFingerprint.resultOrThrow().mutableMethod.apply { + val literIndex = indexOfFirstWideLiteralInstructionValueOrThrow(ReelWatchPlayer) + 2 + val registerIndex = indexOfFirstInstructionOrThrow(literIndex) { + opcode == Opcode.MOVE_RESULT_OBJECT } + val viewRegister = getInstruction(registerIndex).registerA + + addInstruction( + registerIndex + 1, + "invoke-static {v$viewRegister}, " + + "$INTEGRATIONS_PLAYER_TYPE_HOOK_CLASS_DESCRIPTOR->onShortsCreate(Landroid/view/View;)V" + ) } // endregion // region patch for set video state - YouTubeControlsOverlayFingerprint.resultOrThrow().let { parentResult -> - VideoStateFingerprint.also { - it.resolve(context, parentResult.classDef) - }.resultOrThrow().let { - it.mutableMethod.apply { - val endIndex = it.scanResult.patternScanResult!!.endIndex - val videoStateFieldName = - getInstruction(endIndex).reference - - addInstructions( - 0, """ - iget-object v0, p1, $videoStateFieldName # copy VideoState parameter field - invoke-static {v0}, $INTEGRATIONS_PLAYER_TYPE_HOOK_CLASS_DESCRIPTOR->setVideoState(Ljava/lang/Enum;)V - """ - ) - } + VideoStateFingerprint.alsoResolve( + context, YouTubeControlsOverlayFingerprint + ).let { + it.mutableMethod.apply { + val endIndex = it.scanResult.patternScanResult!!.endIndex + val videoStateFieldName = + getInstruction(endIndex).reference + + addInstructions( + 0, """ + iget-object v0, p1, $videoStateFieldName # copy VideoState parameter field + invoke-static {v0}, $INTEGRATIONS_PLAYER_TYPE_HOOK_CLASS_DESCRIPTOR->setVideoState(Ljava/lang/Enum;)V + """ + ) } } @@ -82,40 +102,37 @@ object PlayerTypeHookPatch : BytecodePatch( BrowseIdClassFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val targetIndex = getStringInstructionIndex("VL") - 1 - val targetReference = getInstruction(targetIndex).reference - val targetClass = - context.findClass((targetReference as FieldReference).definingClass)!!.mutableClass - - targetClass.methods.find { method -> method.name == "" } - ?.apply { - val browseIdFieldIndex = getTargetIndexOrThrow(Opcode.IPUT_OBJECT) - val browseIdFieldName = - (getInstruction(browseIdFieldIndex).reference as FieldReference).name - - val smaliInstructions = + val targetIndex = indexOfFirstStringInstructionOrThrow("VL") - 1 + val targetClass = getInstruction(targetIndex) + .getReference() + ?.definingClass + ?: throw PatchException("Could not find browseId class") + + context.findMethodOrThrow(targetClass).apply { + val browseIdFieldReference = getInstruction( + indexOfFirstInstructionOrThrow(Opcode.IPUT_OBJECT) + ).reference + val browseIdFieldName = (browseIdFieldReference as FieldReference).name + + val smaliInstructions = + """ + if-eqz v0, :ignore + iget-object v0, v0, $definingClass->$browseIdFieldName:Ljava/lang/String; + if-eqz v0, :ignore + return-object v0 + :ignore + const-string v0, "" + return-object v0 """ - if-eqz v0, :ignore - iget-object v0, v0, $definingClass->$browseIdFieldName:Ljava/lang/String; - if-eqz v0, :ignore - return-object v0 - :ignore - const-string v0, "" - return-object v0 - """ - - val rootViewMutableClass = - context.findClass(INTEGRATIONS_ROOT_VIEW_HOOK_CLASS_DESCRIPTOR)!!.mutableClass - - rootViewMutableClass.addFieldAndInstructions( - context, - "getBrowseId", - "browseIdClass", - definingClass, - smaliInstructions, - true - ) - } ?: throw PatchException("BrowseIdClass not found!") + + context.addStaticFieldToIntegration( + INTEGRATIONS_ROOT_VIEW_HOOK_CLASS_DESCRIPTOR, + "getBrowseId", + "browseIdClass", + definingClass, + smaliInstructions + ) + } } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/fingerprint/ActionBarSearchResultsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/fingerprint/ActionBarSearchResultsFingerprint.kt index 1a6452a6f..d14e8a9e5 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/fingerprint/ActionBarSearchResultsFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/fingerprint/ActionBarSearchResultsFingerprint.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.playertype.fingerprint.ActionBarSearchResultsFingerprint.indexOfLayoutDirectionInstruction import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ActionBarSearchResultsViewMic -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.AccessFlags @@ -16,7 +16,7 @@ internal object ActionBarSearchResultsFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, returnType = "Landroid/view/View;", customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(ActionBarSearchResultsViewMic) && + methodDef.containsWideLiteralInstructionValue(ActionBarSearchResultsViewMic) && indexOfLayoutDirectionInstruction(methodDef) >= 0 } ) { diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/fingerprint/ReelWatchPagerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/fingerprint/ReelWatchPagerFingerprint.kt new file mode 100644 index 000000000..7bb7d066b --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/fingerprint/ReelWatchPagerFingerprint.kt @@ -0,0 +1,12 @@ +package app.revanced.patches.youtube.utils.playertype.fingerprint + +import app.revanced.patcher.extensions.or +import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelWatchPlayer +import app.revanced.util.fingerprint.LiteralValueFingerprint +import com.android.tools.smali.dexlib2.AccessFlags + +internal object ReelWatchPagerFingerprint : LiteralValueFingerprint( + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + returnType = "Landroid/view/View;", + literalSupplier = { ReelWatchPlayer } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/recyclerview/BottomSheetRecyclerViewPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/recyclerview/BottomSheetRecyclerViewPatch.kt index b04544925..560fd7437 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/recyclerview/BottomSheetRecyclerViewPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/recyclerview/BottomSheetRecyclerViewPatch.kt @@ -2,18 +2,16 @@ package app.revanced.patches.youtube.utils.recyclerview import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.youtube.utils.recyclerview.fingerprints.BottomSheetRecyclerViewBuilderFingerprint import app.revanced.patches.youtube.utils.recyclerview.fingerprints.RecyclerViewTreeObserverFingerprint import app.revanced.util.getReference -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.getWideLiteralInstructionIndex import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.FieldReference object BottomSheetRecyclerViewPatch : BytecodePatch( @@ -35,15 +33,10 @@ object BottomSheetRecyclerViewPatch : BytecodePatch( * Therefore, we need to force this to be true. */ BottomSheetRecyclerViewBuilderFingerprint.result?.let { - it.mutableMethod.apply { - val targetIndex = getWideLiteralInstructionIndex(45382015) + 2 - val targetRegister = getInstruction(targetIndex).registerA - - addInstruction( - targetIndex + 1, - "const/4 v$targetRegister, 0x1" - ) - } + BottomSheetRecyclerViewBuilderFingerprint.injectLiteralInstructionBooleanCall( + 45382015, + "0x1" + ) } RecyclerViewTreeObserverFingerprint.resultOrThrow().mutableMethod.apply { @@ -54,7 +47,7 @@ object BottomSheetRecyclerViewPatch : BytecodePatch( && getReference()?.type == "Landroid/view/ViewTreeObserver${'$'}OnDrawListener;" } recyclerViewTreeObserverInsertIndex = - getTargetIndexReversedOrThrow(onDrawListenerIndex, Opcode.CHECK_CAST) + 1 + indexOfFirstInstructionReversedOrThrow(onDrawListenerIndex, Opcode.CHECK_CAST) + 1 } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt index 82361b9f6..a8c77ce03 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt @@ -31,6 +31,7 @@ object SharedResourceIdPatch : ResourcePatch() { var BadgeLabel = -1L var Bar = -1L var BarContainerHeight = -1L + var BottomBarContainer = -1L var BottomSheetFooterText = -1L var BottomSheetRecyclerView = -1L var BottomUiContainerStub = -1L @@ -44,6 +45,7 @@ object SharedResourceIdPatch : ResourcePatch() { var ControlsLayoutStub = -1L var DarkBackground = -1L var DarkSplashAnimation = -1L + var DesignBottomSheet = -1L var DonationCompanion = -1L var DrawerContentView = -1L var DrawerResults = -1L @@ -94,6 +96,7 @@ object SharedResourceIdPatch : ResourcePatch() { var ReelRightLikeIcon = -1L var ReelTimeBarPlayedColor = -1L var ReelVodTimeStampsContainer = -1L + var ReelWatchPlayer = -1L var RelatedChipCloudMargin = -1L var RightComment = -1L var ScrimOverlay = -1L @@ -136,6 +139,7 @@ object SharedResourceIdPatch : ResourcePatch() { BadgeLabel = getId(ID, "badge_label") Bar = getId(LAYOUT, "bar") BarContainerHeight = getId(DIMEN, "bar_container_height") + BottomBarContainer = getId(ID, "bottom_bar_container") BottomSheetFooterText = getId(ID, "bottom_sheet_footer_text") BottomSheetRecyclerView = getId(LAYOUT, "bottom_sheet_recycler_view") BottomUiContainerStub = getId(ID, "bottom_ui_container_stub") @@ -149,6 +153,7 @@ object SharedResourceIdPatch : ResourcePatch() { ControlsLayoutStub = getId(ID, "controls_layout_stub") DarkBackground = getId(ID, "dark_background") DarkSplashAnimation = getId(ID, "dark_splash_animation") + DesignBottomSheet = getId(ID, "design_bottom_sheet") DonationCompanion = getId(LAYOUT, "donation_companion") DrawerContentView = getId(ID, "drawer_content_view") DrawerResults = getId(ID, "drawer_results") @@ -202,6 +207,7 @@ object SharedResourceIdPatch : ResourcePatch() { ReelRightLikeIcon = getId(DRAWABLE, "reel_right_like_icon") ReelTimeBarPlayedColor = getId(COLOR, "reel_time_bar_played_color") ReelVodTimeStampsContainer = getId(ID, "reel_vod_timestamps_container") + ReelWatchPlayer = getId(ID, "reel_watch_player") RelatedChipCloudMargin = getId(LAYOUT, "related_chip_cloud_reduced_margins") RightComment = getId(DRAWABLE, "ic_right_comment_32c") ScrimOverlay = getId(ID, "scrim_overlay") diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/general/ReturnYouTubeDislikePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/general/ReturnYouTubeDislikePatch.kt index 4095c72af..a580ea3ca 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/general/ReturnYouTubeDislikePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/general/ReturnYouTubeDislikePatch.kt @@ -20,16 +20,15 @@ import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.video.information.VideoInformationPatch import app.revanced.patches.youtube.video.videoid.VideoIdPatch import app.revanced.util.getReference -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithFieldReferenceType -import app.revanced.util.getTargetIndexWithFieldReferenceTypeOrThrow import app.revanced.util.indexOfFirstInstruction +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Suppress("unused") @@ -78,13 +77,15 @@ object ReturnYouTubeDislikePatch : BaseBytecodePatch( TextComponentContextFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val conversionContextFieldIndex = - getTargetIndexWithFieldReferenceTypeOrThrow("Ljava/util/Map;") - 1 + val conversionContextFieldIndex = indexOfFirstInstructionOrThrow { + getReference()?.type == "Ljava/util/Map;" + } - 1 val conversionContextFieldReference = getInstruction(conversionContextFieldIndex).reference - val charSequenceIndex1932 = - getTargetIndexWithFieldReferenceType("Ljava/util/BitSet;") - 1 + val charSequenceIndex1932 = indexOfFirstInstruction { + getReference()?.type == "Ljava/util/BitSet;" + } - 1 val charSequenceIndex1933 = indexOfFirstInstruction { val reference = getReference() opcode == Opcode.INVOKE_VIRTUAL && @@ -108,7 +109,7 @@ object ReturnYouTubeDislikePatch : BaseBytecodePatch( } val freeRegister = getInstruction( - getTargetIndexOrThrow(insertIndex, Opcode.IGET_OBJECT) + indexOfFirstInstructionOrThrow(insertIndex, Opcode.IGET_OBJECT) ).registerA addInstructions( diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/ReturnYouTubeDislikeRollingNumberPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/ReturnYouTubeDislikeRollingNumberPatch.kt index 29490b004..22256003b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/ReturnYouTubeDislikeRollingNumberPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/ReturnYouTubeDislikeRollingNumberPatch.kt @@ -6,7 +6,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.youtube.utils.fingerprints.RollingNumberTextViewAnimationUpdateFingerprint @@ -17,15 +16,17 @@ import app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fin import app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fingerprints.RollingNumberMeasureTextParentFingerprint import app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fingerprints.RollingNumberSetterFingerprint import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.alsoResolve +import app.revanced.util.findMethodOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode 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.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction -import com.android.tools.smali.dexlib2.iface.reference.Reference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Patch(dependencies = [SettingsPatch::class]) object ReturnYouTubeDislikeRollingNumberPatch : BytecodePatch( @@ -46,127 +47,115 @@ object ReturnYouTubeDislikeRollingNumberPatch : BytecodePatch( * In order to maintain compatibility with YouTube v18.48.39 or previous versions, * This patch is applied only to the version after YouTube v18.49.37 */ - if (SettingsPatch.upward1849) { - - RollingNumberSetterFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - val rollingNumberClassIndex = it.scanResult.patternScanResult!!.startIndex - val rollingNumberClassReference = - getInstruction(rollingNumberClassIndex).reference - val rollingNumberClass = - context.findClass(rollingNumberClassReference.toString())!!.mutableClass - - lateinit var charSequenceFieldReference: Reference - - rollingNumberClass.methods.find { method -> method.name == "" } - ?.apply { - val rollingNumberFieldIndex = getTargetIndexOrThrow(Opcode.IPUT_OBJECT) - charSequenceFieldReference = - getInstruction(rollingNumberFieldIndex).reference - } ?: throw PatchException("RollingNumberClass not found!") - - val insertIndex = rollingNumberClassIndex + 1 + if (!SettingsPatch.upward1849) { + return + } - val charSequenceInstanceRegister = - getInstruction(rollingNumberClassIndex).registerA + RollingNumberSetterFingerprint.resultOrThrow().let { + it.mutableMethod.apply { + val rollingNumberClassIndex = it.scanResult.patternScanResult!!.startIndex + val rollingNumberClassReference = + getInstruction(rollingNumberClassIndex).reference.toString() + val rollingNumberConstructorMethod = + context.findMethodOrThrow(rollingNumberClassReference) + val charSequenceFieldReference = with(rollingNumberConstructorMethod) { + getInstruction( + indexOfFirstInstructionOrThrow(Opcode.IPUT_OBJECT) + ).reference + } - val registerCount = implementation!!.registerCount + val insertIndex = rollingNumberClassIndex + 1 + val charSequenceInstanceRegister = + getInstruction(rollingNumberClassIndex).registerA + val registerCount = implementation!!.registerCount - // This register is being overwritten, so it is free to use. - val freeRegister = registerCount - 1 - val conversionContextRegister = registerCount - parameters.size + 1 + // This register is being overwritten, so it is free to use. + val freeRegister = registerCount - 1 + val conversionContextRegister = registerCount - parameters.size + 1 - addInstructions( - insertIndex, """ + addInstructions( + insertIndex, """ iget-object v$freeRegister, v$charSequenceInstanceRegister, $charSequenceFieldReference invoke-static {v$conversionContextRegister, v$freeRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberLoaded(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String; move-result-object v$freeRegister iput-object v$freeRegister, v$charSequenceInstanceRegister, $charSequenceFieldReference """ - ) - } + ) } + } - // Rolling Number text views use the measured width of the raw string for layout. - // Modify the measure text calculation to include the left drawable separator if needed. - RollingNumberMeasureAnimatedTextFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - val endIndex = it.scanResult.patternScanResult!!.endIndex - val measuredTextWidthIndex = endIndex - 2 - val measuredTextWidthRegister = - getInstruction(measuredTextWidthIndex).registerA - - addInstructions( - endIndex + 1, """ - invoke-static {p1, v$measuredTextWidthRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F - move-result v$measuredTextWidthRegister - """ - ) - - val ifGeIndex = getTargetIndexOrThrow(Opcode.IF_GE) - val ifGeInstruction = getInstruction(ifGeIndex) - - removeInstruction(ifGeIndex) - addInstructionsWithLabels( - ifGeIndex, """ - if-ge v${ifGeInstruction.registerA}, v${ifGeInstruction.registerB}, :jump - """, ExternalLabel("jump", getInstruction(endIndex)) - ) - } + // Rolling Number text views use the measured width of the raw string for layout. + // Modify the measure text calculation to include the left drawable separator if needed. + RollingNumberMeasureAnimatedTextFingerprint.resultOrThrow().let { + it.mutableMethod.apply { + val endIndex = it.scanResult.patternScanResult!!.endIndex + val measuredTextWidthIndex = endIndex - 2 + val measuredTextWidthRegister = + getInstruction(measuredTextWidthIndex).registerA + + addInstructions( + endIndex + 1, """ + invoke-static {p1, v$measuredTextWidthRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F + move-result v$measuredTextWidthRegister + """ + ) + + val ifGeIndex = indexOfFirstInstructionOrThrow(opcode = Opcode.IF_GE) + val ifGeInstruction = getInstruction(ifGeIndex) + + removeInstruction(ifGeIndex) + addInstructionsWithLabels( + ifGeIndex, """ + if-ge v${ifGeInstruction.registerA}, v${ifGeInstruction.registerB}, :jump + """, ExternalLabel("jump", getInstruction(endIndex)) + ) } + } - RollingNumberMeasureTextParentFingerprint.resultOrThrow().classDef.let { parentClassDef -> - RollingNumberMeasureStaticLabelFingerprint.resolve(context, parentClassDef) - - // Additional text measurement method. Used if YouTube decides not to animate the likes count - // and sometimes used for initial video load. - RollingNumberMeasureStaticLabelFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - val measureTextIndex = it.scanResult.patternScanResult!!.startIndex + 1 - val freeRegister = getInstruction(0).registerA - - addInstructions( - measureTextIndex + 1, """ - move-result v$freeRegister - invoke-static {p1, v$freeRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F - """ - ) - } - } + RollingNumberMeasureStaticLabelFingerprint.alsoResolve( + context, + RollingNumberMeasureTextParentFingerprint + ).let { + it.mutableMethod.apply { + val measureTextIndex = it.scanResult.patternScanResult!!.startIndex + 1 + val freeRegister = getInstruction(0).registerA + + addInstructions( + measureTextIndex + 1, """ + move-result v$freeRegister + invoke-static {p1, v$freeRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F + """ + ) } + } - // The rolling number Span is missing styling since it's initially set as a String. - // Modify the UI text view and use the styled like/dislike Span. - RollingNumberTextViewFingerprint.resultOrThrow().let { parentResult -> - // Initial TextView is set in this method. - val initiallyCreatedTextViewMethod = parentResult.mutableMethod - - // Video less than 24 hours after uploaded, like counts will be updated in real time. - // Whenever like counts are updated, TextView is set in this method. - val realTimeUpdateTextViewMethod = - RollingNumberTextViewAnimationUpdateFingerprint.also { - it.resolve(context, parentResult.classDef) - }.resultOrThrow().mutableMethod - - arrayOf( - initiallyCreatedTextViewMethod, - realTimeUpdateTextViewMethod - ).forEach { insertMethod -> - insertMethod.apply { - val setTextIndex = getTargetIndexWithMethodReferenceNameOrThrow("setText") - val textViewRegister = - getInstruction(setTextIndex).registerC - val textSpanRegister = - getInstruction(setTextIndex).registerD - - addInstructions( - setTextIndex, """ - invoke-static {v$textViewRegister, v$textSpanRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->updateRollingNumber(Landroid/widget/TextView;Ljava/lang/CharSequence;)Ljava/lang/CharSequence; - move-result-object v$textSpanRegister - """ - ) - } + // The rolling number Span is missing styling since it's initially set as a String. + // Modify the UI text view and use the styled like/dislike Span. + arrayOf( + // Initial TextView is set in this method. + RollingNumberTextViewFingerprint + .resultOrThrow(), + + // Video less than 24 hours after uploaded, like counts will be updated in real time. + // Whenever like counts are updated, TextView is set in this method. + RollingNumberTextViewAnimationUpdateFingerprint + .alsoResolve(context, RollingNumberTextViewFingerprint) + ).forEach { fingerprintResult -> + fingerprintResult.mutableMethod.apply { + val setTextIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "setText" } + val textViewRegister = + getInstruction(setTextIndex).registerC + val textSpanRegister = + getInstruction(setTextIndex).registerD + + addInstructions( + setTextIndex, """ + invoke-static {v$textViewRegister, v$textSpanRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->updateRollingNumber(Landroid/widget/TextView;Ljava/lang/CharSequence;)Ljava/lang/CharSequence; + move-result-object v$textSpanRegister + """ + ) } } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/fingerprints/RollingNumberMeasureAnimatedTextFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/fingerprints/RollingNumberMeasureAnimatedTextFingerprint.kt index 80ceaec83..a15449332 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/fingerprints/RollingNumberMeasureAnimatedTextFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/fingerprints/RollingNumberMeasureAnimatedTextFingerprint.kt @@ -1,12 +1,15 @@ package app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fingerprints -import app.revanced.util.fingerprint.ReferenceFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.reference.MethodReference /** * This fingerprint is compatible with YouTube v18.30.xx+ */ -internal object RollingNumberMeasureAnimatedTextFingerprint : ReferenceFingerprint( +internal object RollingNumberMeasureAnimatedTextFingerprint : MethodFingerprint( opcodes = listOf( Opcode.INVOKE_VIRTUAL, Opcode.MOVE_RESULT, @@ -14,5 +17,9 @@ internal object RollingNumberMeasureAnimatedTextFingerprint : ReferenceFingerpri Opcode.ADD_INT_LIT8, Opcode.GOTO ), - reference = { "Landroid/text/TextPaint;->measureText([CII)F" } + customFingerprint = { methodDef, _ -> + methodDef.indexOfFirstInstruction { + getReference()?.toString() == "Landroid/text/TextPaint;->measureText([CII)F" + } >= 0 + } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/shorts/ReturnYouTubeDislikeShortsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/shorts/ReturnYouTubeDislikeShortsPatch.kt index cdb6c8946..d174f5ece 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/shorts/ReturnYouTubeDislikeShortsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/shorts/ReturnYouTubeDislikeShortsPatch.kt @@ -12,14 +12,15 @@ import app.revanced.patches.youtube.utils.fingerprints.TextComponentSpecFingerpr import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH import app.revanced.patches.youtube.utils.returnyoutubedislike.shorts.fingerprints.ShortsTextViewFingerprint import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.getTargetIndexWithReferenceOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Patch(dependencies = [SettingsPatch::class]) object ReturnYouTubeDislikeShortsPatch : BytecodePatch( @@ -37,9 +38,9 @@ object ReturnYouTubeDislikeShortsPatch : BytecodePatch( val startIndex = it.scanResult.patternScanResult!!.startIndex val isDisLikesBooleanIndex = - getTargetIndexReversedOrThrow(startIndex, Opcode.IGET_BOOLEAN) + indexOfFirstInstructionReversedOrThrow(startIndex, Opcode.IGET_BOOLEAN) val textViewFieldIndex = - getTargetIndexReversedOrThrow(startIndex, Opcode.IGET_OBJECT) + indexOfFirstInstructionReversedOrThrow(startIndex, Opcode.IGET_OBJECT) // If the field is true, the TextView is for a dislike button. val isDisLikesBooleanReference = @@ -51,7 +52,7 @@ object ReturnYouTubeDislikeShortsPatch : BytecodePatch( // Check if the hooked TextView object is that of the dislike button. // If RYD is disabled, or the TextView object is not that of the dislike button, the execution flow is not interrupted. // Otherwise, the TextView object is modified, and the execution flow is interrupted to prevent it from being changed afterward. - val insertIndex = getTargetIndexOrThrow(Opcode.CHECK_CAST) + 1 + val insertIndex = indexOfFirstInstructionOrThrow(Opcode.CHECK_CAST) + 1 addInstructionsWithLabels( insertIndex, """ @@ -70,29 +71,30 @@ object ReturnYouTubeDislikeShortsPatch : BytecodePatch( } } - if (SettingsPatch.upward1834) { - TextComponentSpecFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - val insertIndex = - getTargetIndexWithReferenceOrThrow("Landroid/text/SpannableString;->valueOf(Ljava/lang/CharSequence;)Landroid/text/SpannableString;") - - val charSequenceRegister = - getInstruction(insertIndex).registerC - val conversionContextRegister = - getInstruction(0).registerA - - val replaceReference = - getInstruction(insertIndex).reference + if (!SettingsPatch.upward1834) { + return + } - addInstructions( - insertIndex + 1, """ - invoke-static {v$conversionContextRegister, v$charSequenceRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onCharSequenceLoaded(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence; - move-result-object v$charSequenceRegister - invoke-static {v$charSequenceRegister}, $replaceReference - """ - ) - removeInstruction(insertIndex) + TextComponentSpecFingerprint.resultOrThrow().let { + it.mutableMethod.apply { + val insertIndex = indexOfFirstInstructionOrThrow { + getReference()?.toString() == "Landroid/text/SpannableString;->valueOf(Ljava/lang/CharSequence;)Landroid/text/SpannableString;" } + val charSequenceRegister = + getInstruction(insertIndex).registerC + val conversionContextRegister = + getInstruction(0).registerA + val replaceReference = + getInstruction(insertIndex).reference + + addInstructions( + insertIndex + 1, """ + invoke-static {v$conversionContextRegister, v$charSequenceRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onCharSequenceLoaded(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence; + move-result-object v$charSequenceRegister + invoke-static {v$charSequenceRegister}, $replaceReference + """ + ) + removeInstruction(insertIndex) } } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/settings/ResourceUtils.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/settings/ResourceUtils.kt index 26c3649ac..451cd2b86 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/settings/ResourceUtils.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/settings/ResourceUtils.kt @@ -50,23 +50,27 @@ object ResourceUtils { } fun ResourceContext.addEntryValues( - path: String, - speedEntryValues: String, - attributeName: String + attributeName: String, + attributeValue: String, + path: String = "res/values/arrays.xml", + prepend: Boolean = true, ) { xmlEditor[path].use { with(it.file) { val resourcesNode = getElementsByTagName("resources").item(0) as Element val newElement: Element = createElement("item") - for (i in 0 until resourcesNode.childNodes.length) { val node = resourcesNode.childNodes.item(i) as? Element ?: continue if (node.getAttribute("name") == attributeName) { - newElement.appendChild(createTextNode(speedEntryValues)) + newElement.appendChild(createTextNode(attributeValue)) - node.appendChild(newElement) + if (prepend) { + node.appendChild(newElement) + } else { + node.insertBefore(newElement, node.firstChild) + } } } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/settings/SettingsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/settings/SettingsPatch.kt index 3e1080232..7b3d48312 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/settings/SettingsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/settings/SettingsPatch.kt @@ -320,7 +320,13 @@ object SettingsPatch : BaseResourcePatch( updatePatchStatus(patch.name!!) } + private val patchList = ArrayList() + internal fun updatePatchStatus(patchName: String) { + patchList.add(patchName) contexts.updatePatchStatus(patchName) } + + internal fun containsPatch(patchName: String) = + patchList.contains(patchName) } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/SponsorBlockBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/SponsorBlockBytecodePatch.kt index 3012c270e..9bda4f425 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/SponsorBlockBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/SponsorBlockBytecodePatch.kt @@ -19,11 +19,11 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.Inset import app.revanced.patches.youtube.utils.sponsorblock.fingerprints.RectangleFieldInvalidatorFingerprint import app.revanced.patches.youtube.utils.sponsorblock.fingerprints.SegmentPlaybackControllerFingerprint import app.revanced.patches.youtube.video.information.VideoInformationPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithFieldReferenceTypeReversedOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameReversedOrThrow -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.alsoResolve +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.resultOrThrow import app.revanced.util.updatePatchStatus import com.android.tools.smali.dexlib2.Opcode @@ -31,6 +31,7 @@ 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.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Patch( dependencies = [ @@ -74,13 +75,11 @@ object SponsorBlockBytecodePatch : BytecodePatch( ) } - val seekBarClass = SeekbarFingerprint.resultOrThrow().mutableClass - SeekbarOnDrawFingerprint.resolve(context, seekBarClass) - RectangleFieldInvalidatorFingerprint.resolve(context, seekBarClass) - - SeekbarOnDrawFingerprint.resultOrThrow().mutableMethod.apply { + SeekbarOnDrawFingerprint.alsoResolve( + context, SeekbarFingerprint + ).mutableMethod.apply { // Get left and right of seekbar rectangle - val moveObjectIndex = getTargetIndexOrThrow(Opcode.MOVE_OBJECT_FROM16) + val moveObjectIndex = indexOfFirstInstructionOrThrow(opcode = Opcode.MOVE_OBJECT_FROM16) addInstruction( moveObjectIndex + 1, @@ -89,7 +88,9 @@ object SponsorBlockBytecodePatch : BytecodePatch( ) // Set seekbar thickness - val roundIndex = getTargetIndexWithMethodReferenceNameOrThrow("round") + 1 + val roundIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "round" + } + 1 val roundRegister = getInstruction(roundIndex).registerA addInstruction( @@ -99,7 +100,9 @@ object SponsorBlockBytecodePatch : BytecodePatch( ) // Draw segment - val drawCircleIndex = getTargetIndexWithMethodReferenceNameReversedOrThrow("drawCircle") + val drawCircleIndex = indexOfFirstInstructionReversedOrThrow { + getReference()?.name == "drawCircle" + } val drawCircleInstruction = getInstruction(drawCircleIndex) addInstruction( drawCircleIndex, @@ -116,7 +119,9 @@ object SponsorBlockBytecodePatch : BytecodePatch( // Append timestamp TotalTimeFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val targetIndex = getTargetIndexWithMethodReferenceNameOrThrow("getString") + 1 + val targetIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "getString" + } + 1 val targetRegister = getInstruction(targetIndex).registerA addInstructions( @@ -131,8 +136,9 @@ object SponsorBlockBytecodePatch : BytecodePatch( // Initialize the SponsorBlock view YouTubeControlsOverlayFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val targetIndex = getWideLiteralInstructionIndex(InsetOverlayViewLayout) - val checkCastIndex = getTargetIndexOrThrow(targetIndex, Opcode.CHECK_CAST) + val targetIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(InsetOverlayViewLayout) + val checkCastIndex = indexOfFirstInstructionOrThrow(targetIndex, Opcode.CHECK_CAST) val targetRegister = getInstruction(checkCastIndex).registerA @@ -144,14 +150,15 @@ object SponsorBlockBytecodePatch : BytecodePatch( } // Replace strings - RectangleFieldInvalidatorFingerprint.resultOrThrow().let { result -> + RectangleFieldInvalidatorFingerprint.alsoResolve( + context, SeekbarFingerprint + ).let { result -> result.mutableMethod.apply { val invalidateIndex = - getTargetIndexWithMethodReferenceNameReversedOrThrow("invalidate") - val rectangleIndex = getTargetIndexWithFieldReferenceTypeReversedOrThrow( - invalidateIndex + 1, - "Landroid/graphics/Rect;" - ) + RectangleFieldInvalidatorFingerprint.indexOfInvalidateInstruction(this) + val rectangleIndex = indexOfFirstInstructionReversedOrThrow(invalidateIndex + 1) { + getReference()?.type == "Landroid/graphics/Rect;" + } val rectangleFieldName = (getInstruction(rectangleIndex).reference as FieldReference).name diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/fingerprints/RectangleFieldInvalidatorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/fingerprints/RectangleFieldInvalidatorFingerprint.kt index 598513e7c..89415c67a 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/fingerprints/RectangleFieldInvalidatorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/fingerprints/RectangleFieldInvalidatorFingerprint.kt @@ -1,9 +1,21 @@ package app.revanced.patches.youtube.utils.sponsorblock.fingerprints -import app.revanced.util.fingerprint.MethodReferenceNameFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.youtube.utils.sponsorblock.fingerprints.RectangleFieldInvalidatorFingerprint.indexOfInvalidateInstruction +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionReversed +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal object RectangleFieldInvalidatorFingerprint : MethodReferenceNameFingerprint( +internal object RectangleFieldInvalidatorFingerprint : MethodFingerprint( returnType = "V", parameters = emptyList(), - reference = { "invalidate" } -) + customFingerprint = { methodDef, _ -> + indexOfInvalidateInstruction(methodDef) >= 0 + } +) { + fun indexOfInvalidateInstruction(methodDef: Method) = + methodDef.indexOfFirstInstructionReversed { + getReference()?.name == "invalidate" + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/trackingurlhook/TrackingUrlHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/trackingurlhook/TrackingUrlHookPatch.kt index b2e2464b6..5012f0c09 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/trackingurlhook/TrackingUrlHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/trackingurlhook/TrackingUrlHookPatch.kt @@ -6,9 +6,12 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.youtube.utils.trackingurlhook.fingerprints.TrackingUrlModelFingerprint -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference object TrackingUrlHookPatch : BytecodePatch( setOf(TrackingUrlModelFingerprint) @@ -22,7 +25,10 @@ object TrackingUrlHookPatch : BytecodePatch( internal fun hookTrackingUrl( descriptor: String ) = trackingUrlMethod.apply { - val targetIndex = getTargetIndexWithMethodReferenceNameOrThrow("parse") + 1 + val targetIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_STATIC && + getReference()?.name == "parse" + } + 1 val targetRegister = getInstruction(targetIndex).registerA var smaliInstruction = "invoke-static {v$targetRegister}, $descriptor" diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt index ddeab2fa5..bda19a0c3 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt @@ -10,11 +10,11 @@ import app.revanced.patcher.fingerprint.MethodFingerprintResult import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patcher.util.proxy.mutableTypes.MutableClass import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.util.smali.toInstructions import app.revanced.patches.shared.fingerprints.MdxPlayerDirectorSetVideoStageFingerprint +import app.revanced.patches.shared.fingerprints.VideoLengthFingerprint import app.revanced.patches.youtube.utils.PlayerResponseModelUtils.PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.PlayerResponseModelUtils.indexOfPlayerResponseModelInstruction import app.revanced.patches.youtube.utils.fingerprints.VideoEndFingerprint @@ -31,20 +31,18 @@ import app.revanced.patches.youtube.video.information.fingerprints.SeekRelativeF import app.revanced.patches.youtube.video.information.fingerprints.VideoIdFingerprint import app.revanced.patches.youtube.video.information.fingerprints.VideoIdFingerprintBackgroundPlay import app.revanced.patches.youtube.video.information.fingerprints.VideoIdFingerprintShorts -import app.revanced.patches.youtube.video.information.fingerprints.VideoLengthFingerprint import app.revanced.patches.youtube.video.information.fingerprints.VideoQualityListFingerprint import app.revanced.patches.youtube.video.information.fingerprints.VideoQualityTextFingerprint import app.revanced.patches.youtube.video.information.fingerprints.VideoTitleFingerprint import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch import app.revanced.patches.youtube.video.videoid.VideoIdPatch -import app.revanced.util.addFieldAndInstructions +import app.revanced.util.addStaticFieldToIntegration import app.revanced.util.alsoResolve import app.revanced.util.getReference -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow import app.revanced.util.getWalkerMethod -import app.revanced.util.getWideLiteralInstructionIndex import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode @@ -122,7 +120,6 @@ object VideoInformationPatch : BytecodePatch( private var seekSourceMethodName = "" private var seekRelativeSourceMethodName = "" - private lateinit var videoInformationMutableClass: MutableClass private lateinit var context: BytecodeContext private lateinit var playerConstructorMethod: MutableMethod @@ -159,7 +156,7 @@ object VideoInformationPatch : BytecodePatch( 4, """ # first enum (field a) is SEEK_SOURCE_UNKNOWN sget-object v0, $seekSourceEnumType->a:$seekSourceEnumType - invoke-virtual {p0, p1, p2, v0}, ${definingClass}->$seekMethodName(J$seekSourceEnumType)Z + invoke-virtual {p0, p1, p2, v0}, $definingClass->$seekMethodName(J$seekSourceEnumType)Z move-result p1 return p1 """.toInstructions(), @@ -180,21 +177,18 @@ object VideoInformationPatch : BytecodePatch( return v0 """ - videoInformationMutableClass.addFieldAndInstructions( - context, + context.addStaticFieldToIntegration( + INTEGRATIONS_CLASS_DESCRIPTOR, methodName, fieldName, definingClass, - smaliInstructions, - true + smaliInstructions ) } } override fun execute(context: BytecodeContext) { this.context = context - videoInformationMutableClass = - context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass VideoEndFingerprint.resultOrThrow().let { it.mutableMethod.apply { @@ -232,9 +226,12 @@ object VideoInformationPatch : BytecodePatch( "videoInformationClass" ) - val literalIndex = getWideLiteralInstructionIndex(45368273) + val literalIndex = indexOfFirstWideLiteralInstructionValueOrThrow(45368273) val walkerIndex = - getTargetIndexReversedOrThrow(literalIndex, Opcode.INVOKE_VIRTUAL_RANGE) + indexOfFirstInstructionReversedOrThrow( + literalIndex, + Opcode.INVOKE_VIRTUAL_RANGE + ) videoEndMethod = getWalkerMethod(context, walkerIndex) @@ -364,10 +361,11 @@ object VideoInformationPatch : BytecodePatch( OnPlaybackSpeedItemClickFingerprint.resultOrThrow().let { it.mutableMethod.apply { speedSelectionInsertMethod = this - val speedSelectionValueInstructionIndex = getTargetIndexOrThrow(Opcode.IGET) + val speedSelectionValueInstructionIndex = + indexOfFirstInstructionOrThrow(Opcode.IGET) val setPlaybackSpeedContainerClassFieldIndex = - getTargetIndexReversedOrThrow( + indexOfFirstInstructionReversedOrThrow( speedSelectionValueInstructionIndex, Opcode.IGET_OBJECT ) @@ -446,8 +444,8 @@ object VideoInformationPatch : BytecodePatch( return-void """ - videoInformationMutableClass.addFieldAndInstructions( - context, + context.addStaticFieldToIntegration( + INTEGRATIONS_CLASS_DESCRIPTOR, "overridePlaybackSpeed", "playbackSpeedClass", playbackSpeedClass, @@ -487,13 +485,12 @@ object VideoInformationPatch : BytecodePatch( return-void """ - videoInformationMutableClass.addFieldAndInstructions( - context, + context.addStaticFieldToIntegration( + INTEGRATIONS_CLASS_DESCRIPTOR, "overrideVideoQuality", "videoQualityClass", videoQualityClass, - smaliInstructions, - true + smaliInstructions ) } @@ -562,7 +559,7 @@ object VideoInformationPatch : BytecodePatch( } ).reference - return "invoke-interface {v${REGISTER_PLAYER_RESPONSE_MODEL}}, $targetReference" + return "invoke-interface {v$REGISTER_PLAYER_RESPONSE_MODEL}, $targetReference" } } @@ -582,7 +579,7 @@ object VideoInformationPatch : BytecodePatch( annotations, null, ImmutableMethodImplementation( - 9, """ + REGISTER_PLAYER_RESPONSE_MODEL + 1, """ $channelIdMethodCall move-result-object v$REGISTER_CHANNEL_ID $channelNameMethodCall @@ -614,7 +611,7 @@ object VideoInformationPatch : BytecodePatch( insert( index, - "v${REGISTER_CHANNEL_ID} .. v${REGISTER_VIDEO_IS_LIVE}", + "v$REGISTER_CHANNEL_ID .. v$REGISTER_VIDEO_IS_LIVE", descriptor ) } @@ -628,7 +625,7 @@ object VideoInformationPatch : BytecodePatch( insert( index, - "v${REGISTER_CHANNEL_ID} .. v${REGISTER_VIDEO_IS_LIVE}", + "v$REGISTER_CHANNEL_ID .. v$REGISTER_VIDEO_IS_LIVE", descriptor ) } @@ -642,7 +639,7 @@ object VideoInformationPatch : BytecodePatch( insert( index, - "v${REGISTER_CHANNEL_ID} .. v${REGISTER_VIDEO_IS_LIVE}", + "v$REGISTER_CHANNEL_ID .. v$REGISTER_VIDEO_IS_LIVE", descriptor ) } diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/VideoIdFingerprintShorts.kt b/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/VideoIdFingerprintShorts.kt index b142dd735..0e419ab53 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/VideoIdFingerprintShorts.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/VideoIdFingerprintShorts.kt @@ -2,9 +2,11 @@ package app.revanced.patches.youtube.video.information.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.PlayerResponseModelUtils.PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR -import app.revanced.util.containsWideLiteralInstructionIndex -import app.revanced.util.getTargetIndexWithFieldReferenceName +import app.revanced.util.containsWideLiteralInstructionValue +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.reference.FieldReference /** * This fingerprint is compatible with all versions of YouTube starting from v18.29.38 to supported versions. @@ -19,9 +21,11 @@ internal object VideoIdFingerprintShorts : MethodFingerprint( Opcode.MOVE_RESULT_OBJECT ), customFingerprint = custom@{ methodDef, _ -> - if (methodDef.containsWideLiteralInstructionIndex(45365621)) + if (methodDef.containsWideLiteralInstructionValue(45365621)) return@custom true - methodDef.getTargetIndexWithFieldReferenceName("reelWatchEndpoint") >= 0 + methodDef.indexOfFirstInstruction { + getReference()?.name == "reelWatchEndpoint" + } >= 0 } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/playback/VideoPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/playback/VideoPlaybackPatch.kt index 23edbf025..6a17f77c8 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/playback/VideoPlaybackPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/playback/VideoPlaybackPatch.kt @@ -33,10 +33,9 @@ import app.revanced.patches.youtube.video.playback.fingerprints.QualitySetterFin import app.revanced.patches.youtube.video.playback.fingerprints.VP9CapabilityFingerprint import app.revanced.patches.youtube.video.videoid.VideoIdPatch import app.revanced.util.getReference -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndexOrThrow import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import app.revanced.util.updatePatchStatus @@ -112,7 +111,8 @@ object VideoPlaybackPatch : BaseBytecodePatch( // region patch for disable HDR video HDRCapabilityFingerprint.resultOrThrow().mutableMethod.apply { - val stringIndex = getStringInstructionIndex("av1_profile_main_10_hdr_10_plus_supported") + val stringIndex = + indexOfFirstStringInstructionOrThrow("av1_profile_main_10_hdr_10_plus_supported") val walkerIndex = indexOfFirstInstructionOrThrow(stringIndex) { val reference = getReference() reference?.parameterTypes == listOf("I", "Landroid/view/Display;") @@ -149,7 +149,8 @@ object VideoPlaybackPatch : BaseBytecodePatch( speedSelectionInsertMethod ).forEach { it.apply { - val speedSelectionValueInstructionIndex = getTargetIndexOrThrow(Opcode.IGET) + val speedSelectionValueInstructionIndex = + indexOfFirstInstructionOrThrow(Opcode.IGET) val speedSelectionValueRegister = getInstruction(speedSelectionValueInstructionIndex).registerA @@ -227,7 +228,7 @@ object VideoPlaybackPatch : BaseBytecodePatch( QualityMenuViewInflateFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = getTargetIndexOrThrow(Opcode.CHECK_CAST) + val insertIndex = indexOfFirstInstructionOrThrow(Opcode.CHECK_CAST) val insertRegister = getInstruction(insertIndex).registerA addInstruction( @@ -240,7 +241,7 @@ object VideoPlaybackPatch : BaseBytecodePatch( it.mutableClass.methods.find { method -> method.name == "onItemClick" } onItemClickMethod?.apply { - val insertIndex = getTargetIndexOrThrow(Opcode.IGET_OBJECT) + val insertIndex = indexOfFirstInstructionOrThrow(Opcode.IGET_OBJECT) val insertRegister = getInstruction(insertIndex).registerA val jumpIndex = indexOfFirstInstructionOrThrow { @@ -291,7 +292,7 @@ object VideoPlaybackPatch : BaseBytecodePatch( AV1CodecFingerprint.result?.let { it.mutableMethod.apply { - val insertIndex = getStringInstructionIndex("video/av01") + val insertIndex = indexOfFirstStringInstructionOrThrow("video/av01") val insertRegister = getInstruction(insertIndex).registerA addInstructions( diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/playback/fingerprints/AV1CodecFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/playback/fingerprints/AV1CodecFingerprint.kt index 30442651b..88e28d7fa 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/playback/fingerprints/AV1CodecFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/playback/fingerprints/AV1CodecFingerprint.kt @@ -2,7 +2,7 @@ package app.revanced.patches.youtube.video.playback.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object AV1CodecFingerprint : MethodFingerprint( @@ -13,6 +13,6 @@ internal object AV1CodecFingerprint : MethodFingerprint( if (methodDef.returnType == "Ljava/util/List;") return@handler false - methodDef.containsWideLiteralInstructionIndex(1987076931) + methodDef.containsWideLiteralInstructionValue(1987076931) } ) diff --git a/src/main/kotlin/app/revanced/util/BytecodeUtils.kt b/src/main/kotlin/app/revanced/util/BytecodeUtils.kt index 702df1930..05b26d759 100644 --- a/src/main/kotlin/app/revanced/util/BytecodeUtils.kt +++ b/src/main/kotlin/app/revanced/util/BytecodeUtils.kt @@ -16,6 +16,7 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableClass import app.revanced.patcher.util.proxy.mutableTypes.MutableField import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod +import app.revanced.util.fingerprint.MultiMethodFingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.Method @@ -25,16 +26,21 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction31i -import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.Reference +import com.android.tools.smali.dexlib2.iface.reference.StringReference import com.android.tools.smali.dexlib2.immutable.ImmutableField import com.android.tools.smali.dexlib2.util.MethodUtil const val REGISTER_TEMPLATE_REPLACEMENT: String = "REGISTER_INDEX" +fun MethodFingerprint.isDeprecated() = + javaClass.annotations[0].toString().contains("Deprecated") + fun MethodFingerprint.resultOrThrow() = result ?: throw exception +fun MultiMethodFingerprint.resultOrThrow() = result.ifEmpty { throw exception } + /** * The [PatchException] of failing to resolve a [MethodFingerprint]. * @@ -43,6 +49,9 @@ fun MethodFingerprint.resultOrThrow() = result ?: throw exception val MethodFingerprint.exception get() = PatchException("Failed to resolve ${this.javaClass.simpleName}") +val MultiMethodFingerprint.exception + get() = PatchException("Failed to resolve ${this.javaClass.simpleName}") + fun MethodFingerprint.alsoResolve(context: BytecodeContext, fingerprint: MethodFingerprint) = also { resolve(context, fingerprint.resultOrThrow().classDef) }.resultOrThrow() @@ -74,7 +83,7 @@ fun MutableClass.transformFields(transform: MutableField.() -> MutableField) { */ fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod) { val transformedMethods = methods.map { it.transform() } - methods.clear() + methods.removeIf { !MethodUtil.isConstructor(it) } methods.addAll(transformedMethods) } @@ -96,45 +105,51 @@ fun MutableMethod.injectHideViewCall( "invoke-static { v$viewRegister }, $classDescriptor->$targetMethod(Landroid/view/View;)V" ) -fun MethodFingerprint.literalInstructionBooleanHook( +fun MethodFingerprint.injectLiteralInstructionBooleanCall( literal: Int, descriptor: String -) = literalInstructionBooleanHook(literal.toLong(), descriptor) +) = injectLiteralInstructionBooleanCall(literal.toLong(), descriptor) -fun MethodFingerprint.literalInstructionBooleanHook( +fun MethodFingerprint.injectLiteralInstructionBooleanCall( literal: Long, descriptor: String ) { resultOrThrow().mutableMethod.apply { - val literalIndex = getWideLiteralInstructionIndex(literal) - val targetIndex = getTargetIndex(literalIndex, Opcode.MOVE_RESULT) + val literalIndex = indexOfFirstWideLiteralInstructionValueOrThrow(literal) + val targetIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT) val targetRegister = getInstruction(targetIndex).registerA - val smaliInstruction = if (descriptor.endsWith("(Z)Z")) - "invoke-static {v$targetRegister}, $descriptor" - else - "invoke-static {}, $descriptor" - - addInstructions( - targetIndex + 1, """ - $smaliInstruction + val smaliInstruction = + if (descriptor.startsWith("0x")) """ + const/16 v$targetRegister, $descriptor + """ + else if (descriptor.endsWith("(Z)Z")) """ + invoke-static {v$targetRegister}, $descriptor move-result v$targetRegister """ + else """ + invoke-static {}, $descriptor + move-result v$targetRegister + """ + + addInstructions( + targetIndex + 1, + smaliInstruction ) } } -fun MethodFingerprint.literalInstructionViewHook( +fun MethodFingerprint.injectLiteralInstructionViewCall( literal: Long, smaliInstruction: String -) = resultOrThrow().mutableMethod.literalInstructionViewHook(literal, smaliInstruction) +) = resultOrThrow().mutableMethod.injectLiteralInstructionViewCall(literal, smaliInstruction) -fun MutableMethod.literalInstructionViewHook( +fun MutableMethod.injectLiteralInstructionViewCall( literal: Long, smaliInstruction: String ) { - val literalIndex = getWideLiteralInstructionIndex(literal) - val targetIndex = getTargetIndex(literalIndex, Opcode.MOVE_RESULT_OBJECT) + val literalIndex = indexOfFirstWideLiteralInstructionValueOrThrow(literal) + val targetIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT_OBJECT) val targetRegister = getInstruction(targetIndex).registerA.toString() addInstructions( @@ -143,7 +158,7 @@ fun MutableMethod.literalInstructionViewHook( ) } -fun BytecodeContext.literalInstructionViewHook( +fun BytecodeContext.injectLiteralInstructionViewCall( literal: Long, smaliInstruction: String ) { @@ -160,14 +175,14 @@ fun BytecodeContext.literalInstructionViewHook( context.proxy(classDef) .mutableClass .findMutableMethodOf(method) - .literalInstructionViewHook(literal, smaliInstruction) + .injectLiteralInstructionViewCall(literal, smaliInstruction) } } } } } -fun BytecodeContext.literalInstructionHook( +fun BytecodeContext.replaceLiteralInstructionCall( literal: Long, smaliInstruction: String ) { @@ -184,7 +199,7 @@ fun BytecodeContext.literalInstructionHook( context.proxy(classDef) .mutableClass .findMutableMethodOf(method).apply { - val index = getWideLiteralInstructionIndex(literal) + val index = indexOfFirstWideLiteralInstructionValueOrThrow(literal) val register = (instruction as OneRegisterInstruction).registerA.toString() @@ -200,25 +215,17 @@ fun BytecodeContext.literalInstructionHook( } /** - * Get the index of the first instruction with the literal value or throw a [PatchException]. + * Get the index of the first [Instruction] that matches the predicate, starting from [startIndex]. * - * @throws [PatchException] if the literal index not found. + * @param startIndex Optional starting index to start searching from. + * @return -1 if the instruction is not found. + * @see indexOfFirstInstructionOrThrow */ -fun Method.indexOfWideLiteralInstructionOrThrow(literal: Long): Int { - val index = getWideLiteralInstructionIndex(literal) - if (index < 0) { - val value = - if (literal >= 2130706432) // 0x7f000000, general resource id - String.format("%#X", literal).lowercase() - else - literal.toString() - - throw PatchException("Found literal value for: '$value' but method does not contain the id: $this") +fun Method.indexOfFirstInstruction(startIndex: Int = 0, opcode: Opcode): Int = + indexOfFirstInstruction(startIndex) { + this.opcode == opcode } - return index -} - /** * Get the index of the first [Instruction] that matches the predicate, starting from [startIndex]. * @@ -227,7 +234,10 @@ fun Method.indexOfWideLiteralInstructionOrThrow(literal: Long): Int { * @see indexOfFirstInstructionOrThrow */ fun Method.indexOfFirstInstruction(startIndex: Int = 0, predicate: Instruction.() -> Boolean): Int { - var instructions = this.implementation!!.instructions + if (implementation == null) { + return -1 + } + var instructions = implementation!!.instructions if (startIndex != 0) { instructions = instructions.drop(startIndex) } @@ -240,6 +250,9 @@ fun Method.indexOfFirstInstruction(startIndex: Int = 0, predicate: Instruction.( } } +fun Method.indexOfFirstInstructionOrThrow(opcode: Opcode): Int = + indexOfFirstInstructionOrThrow(0, opcode) + /** * Get the index of the first [Instruction] that matches the predicate, starting from [startIndex]. * @@ -247,11 +260,14 @@ fun Method.indexOfFirstInstruction(startIndex: Int = 0, predicate: Instruction.( * @throws PatchException * @see indexOfFirstInstruction */ -fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, targetOpcode: Opcode): Int = +fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, opcode: Opcode): Int = indexOfFirstInstructionOrThrow(startIndex) { - opcode == targetOpcode + this.opcode == opcode } +fun Method.indexOfFirstInstructionReversedOrThrow(opcode: Opcode): Int = + indexOfFirstInstructionReversedOrThrow(null, opcode) + /** * Get the index of the first [Instruction] that matches the predicate, starting from [startIndex]. * @@ -278,9 +294,9 @@ fun Method.indexOfFirstInstructionOrThrow( * @return -1 if the instruction is not found. * @see indexOfFirstInstructionReversedOrThrow */ -fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, targetOpcode: Opcode): Int = +fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, opcode: Opcode): Int = indexOfFirstInstructionReversed(startIndex) { - opcode == targetOpcode + this.opcode == opcode } /** @@ -295,7 +311,10 @@ fun Method.indexOfFirstInstructionReversed( startIndex: Int? = null, predicate: Instruction.() -> Boolean ): Int { - var instructions = this.implementation!!.instructions + if (implementation == null) { + return -1 + } + var instructions = implementation!!.instructions if (startIndex != null) { instructions = instructions.take(startIndex + 1) } @@ -313,10 +332,10 @@ fun Method.indexOfFirstInstructionReversed( */ fun Method.indexOfFirstInstructionReversedOrThrow( startIndex: Int? = null, - targetOpcode: Opcode + opcode: Opcode ): Int = indexOfFirstInstructionReversedOrThrow(startIndex) { - opcode == targetOpcode + this.opcode == opcode } /** @@ -365,40 +384,59 @@ fun Method.findOpcodeIndicesReversed(filter: Instruction.() -> Boolean): List (instruction as? WideLiteralInstruction)?.wideLiteral == literal } } ?: -1 -fun Method.getStringInstructionIndex(value: String) = implementation?.let { - it.instructions.indexOfFirst { instruction -> - instruction.opcode == Opcode.CONST_STRING - && (instruction as? ReferenceInstruction)?.reference.toString() == value + +/** + * Find the index of the first wide literal instruction with the given value, + * or throw an exception if not found. + * + * @return the first literal instruction with the value, or throws [PatchException] if not found. + */ +fun Method.indexOfFirstWideLiteralInstructionValueOrThrow(literal: Long): Int { + val index = indexOfFirstWideLiteralInstructionValue(literal) + if (index < 0) { + val value = + if (literal >= 2130706432) // 0x7f000000, general resource id + String.format("%#X", literal).lowercase() + else + literal.toString() + + throw PatchException("Found literal value: '$value' but method does not contain the id: $this") } -} ?: -1 -fun Method.getStartsWithStringInstructionIndex(value: String) = implementation?.let { - it.instructions.indexOfFirst { instruction -> - instruction.opcode == Opcode.CONST_STRING - && (instruction as? ReferenceInstruction)?.reference.toString().startsWith(value) + return index +} + +fun Method.indexOfFirstStringInstruction(str: String) = + indexOfFirstInstruction { + opcode == Opcode.CONST_STRING && + getReference()?.string == str + } + + +fun Method.indexOfFirstStringInstructionOrThrow(str: String): Int { + val index = indexOfFirstStringInstruction(str) + if (index < 0) { + throw PatchException("Found string value for: '$str' but method does not contain the id: $this") } -} ?: -1 + + return index +} /** * Check if the method contains a literal with the given value. * * @return if the method contains a literal with the given value. */ -fun Method.containsWideLiteralInstructionIndex(literal: Long) = - getWideLiteralInstructionIndex(literal) >= 0 - -fun Method.containsMethodReferenceNameInstructionIndex(methodName: String) = - getTargetIndexWithMethodReferenceName(methodName) >= 0 - -fun Method.containsReferenceInstructionIndex(reference: String) = - getTargetIndexWithReference(reference) >= 0 +fun Method.containsWideLiteralInstructionValue(literal: Long) = + indexOfFirstWideLiteralInstructionValue(literal) >= 0 /** * Traverse the class hierarchy starting from the given root class. @@ -427,391 +465,113 @@ fun BytecodeContext.traverseClassHierarchy( inline fun Instruction.getReference() = (this as? ReferenceInstruction)?.reference as? T -/** - * Get the index of the first [Instruction] that matches the predicate. - * - * @param predicate The predicate to match. - * @return The index of the first [Instruction] that matches the predicate. - */ -fun Method.indexOfFirstInstruction(predicate: Instruction.() -> Boolean) = - indexOfFirstInstruction(0, predicate) - -/** - * Get the index of the first [Instruction] that matches the predicate, starting from [startIndex]. - * - * @param startIndex Optional starting index to start searching from. - * @return -1 if the instruction is not found. - * @see indexOfFirstInstructionOrThrow - */ -fun Method.indexOfFirstInstruction(startIndex: Int = 0, targetOpcode: Opcode): Int = - indexOfFirstInstruction(startIndex) { - opcode == targetOpcode - } - -fun MutableMethod.getTargetIndexOrThrow(opcode: Opcode) = - getTargetIndexOrThrow(0, opcode) - -fun MutableMethod.getTargetIndexOrThrow(startIndex: Int, opcode: Opcode) = - checkIndex(getTargetIndex(startIndex, opcode), startIndex, opcode) - -fun MutableMethod.getTargetIndexReversedOrThrow(opcode: Opcode) = - getTargetIndexReversedOrThrow(implementation!!.instructions.lastIndex, opcode) - -fun MutableMethod.getTargetIndexReversedOrThrow(startIndex: Int, opcode: Opcode) = - checkIndex(getTargetIndexReversed(startIndex, opcode), startIndex, opcode) - -fun Method.getTargetIndexWithFieldReferenceNameOrThrow(filedName: String) = - checkIndex(getTargetIndexWithFieldReferenceName(filedName), 0, filedName) - -fun MutableMethod.getTargetIndexWithFieldReferenceNameOrThrow(startIndex: Int, filedName: String) = - checkIndex(getTargetIndexWithFieldReferenceName(startIndex, filedName), startIndex, filedName) - -fun MutableMethod.getTargetIndexWithFieldReferenceNameReversedOrThrow(returnType: String) = - getTargetIndexWithFieldReferenceNameReversedOrThrow( - implementation!!.instructions.lastIndex, - returnType - ) - -fun MutableMethod.getTargetIndexWithFieldReferenceNameReversedOrThrow( - startIndex: Int, - returnType: String -) = - checkIndex( - getTargetIndexWithFieldReferenceNameReversed(startIndex, returnType), - startIndex, - returnType - ) - -fun Method.getTargetIndexWithFieldReferenceTypeOrThrow(returnType: String) = - checkIndex(getTargetIndexWithFieldReferenceType(returnType), 0, returnType) - -fun MutableMethod.getTargetIndexWithFieldReferenceTypeOrThrow(startIndex: Int, returnType: String) = - checkIndex(getTargetIndexWithFieldReferenceType(startIndex, returnType), startIndex, returnType) - -fun MutableMethod.getTargetIndexWithFieldReferenceTypeReversedOrThrow(returnType: String) = - getTargetIndexWithFieldReferenceTypeReversedOrThrow( - implementation!!.instructions.lastIndex, - returnType - ) - -fun MutableMethod.getTargetIndexWithFieldReferenceTypeReversedOrThrow( - startIndex: Int, - returnType: String -) = - checkIndex( - getTargetIndexWithFieldReferenceTypeReversed(startIndex, returnType), - startIndex, - returnType - ) - -fun Method.getTargetIndexWithMethodReferenceNameOrThrow(methodName: String) = - checkIndex(getTargetIndexWithMethodReferenceName(methodName), 0, methodName) - -fun MutableMethod.getTargetIndexWithMethodReferenceNameOrThrow( - startIndex: Int, - methodName: String -) = - checkIndex( - getTargetIndexWithMethodReferenceName(startIndex, methodName), - startIndex, - methodName - ) - -fun MutableMethod.getTargetIndexWithMethodReferenceNameReversedOrThrow(methodName: String) = - getTargetIndexWithMethodReferenceNameReversedOrThrow( - implementation!!.instructions.lastIndex, - methodName - ) - -fun MutableMethod.getTargetIndexWithMethodReferenceNameReversedOrThrow( - startIndex: Int, - methodName: String -) = - checkIndex( - getTargetIndexWithMethodReferenceNameReversed(startIndex, methodName), - startIndex, - methodName - ) - -fun Method.getTargetIndexWithReferenceOrThrow(reference: String) = - checkIndex(getTargetIndexWithReference(reference), 0, reference) - -fun MutableMethod.getTargetIndexWithReferenceOrThrow(startIndex: Int, reference: String) = - checkIndex(getTargetIndexWithReference(startIndex, reference), startIndex, reference) - -fun MutableMethod.getTargetIndexWithReferenceReversedOrThrow(reference: String) = - getTargetIndexWithReferenceReversedOrThrow(implementation!!.instructions.lastIndex, reference) - -fun MutableMethod.getTargetIndexWithReferenceReversedOrThrow(startIndex: Int, reference: String) = - checkIndex(getTargetIndexWithReferenceReversed(startIndex, reference), startIndex, reference) - -fun checkIndex(index: Int, startIndex: Int, opcode: Opcode): Int { - if (index < 0) { - throw PatchException("Target index not found. startIndex: $startIndex, opcode: $opcode") - } - return index -} - -fun checkIndex(index: Int, startIndex: Int, name: String): Int { - if (index < 0) { - throw PatchException("Target index not found. startIndex: $startIndex, name: $name") - } - return index -} - -fun MutableMethod.getTargetIndex(opcode: Opcode) = getTargetIndex(0, opcode) - -fun MutableMethod.getTargetIndex(startIndex: Int, opcode: Opcode) = - implementation!!.instructions.let { - startIndex + it.subList(startIndex, it.size - 1).indexOfFirst { instruction -> - instruction.opcode == opcode - } - } - -fun MutableMethod.getTargetIndexReversed(opcode: Opcode) = - getTargetIndexReversed(implementation!!.instructions.size - 1, opcode) - -fun MutableMethod.getTargetIndexReversed(startIndex: Int, opcode: Opcode): Int { - for (index in startIndex downTo 0) { - if (getInstruction(index).opcode != opcode) - continue - - return index - } - return -1 -} - -fun Method.getTargetIndexWithFieldReferenceName(filedName: String) = implementation?.let { - it.instructions.indexOfFirst { instruction -> - instruction.getReference()?.name == filedName - } -} ?: -1 - -fun MutableMethod.getTargetIndexWithFieldReferenceName(startIndex: Int, filedName: String) = - implementation!!.instructions.let { - startIndex + it.subList(startIndex, it.lastIndex).indexOfFirst { instruction -> - instruction.getReference()?.name == filedName - } - } - -fun MutableMethod.getTargetIndexWithFieldReferenceNameReversed(returnType: String) = - getTargetIndexWithFieldReferenceTypeReversed( - implementation!!.instructions.lastIndex, - returnType - ) - -fun MutableMethod.getTargetIndexWithFieldReferenceNameReversed( - startIndex: Int, - filedName: String -): Int { - for (index in startIndex downTo 0) { - val instruction = getInstruction(index) - if (instruction.getReference()?.name != filedName) - continue - - return index - } - return -1 -} - -fun Method.getTargetIndexWithFieldReferenceType(returnType: String) = implementation?.let { - it.instructions.indexOfFirst { instruction -> - instruction.getReference()?.type == returnType - } -} ?: -1 - -fun MutableMethod.getTargetIndexWithFieldReferenceTypeReversed(returnType: String) = - getTargetIndexWithFieldReferenceTypeReversed(implementation!!.instructions.size - 1, returnType) - -fun MutableMethod.getTargetIndexWithFieldReferenceType(startIndex: Int, returnType: String) = - implementation!!.instructions.let { - startIndex + it.subList(startIndex, it.size - 1).indexOfFirst { instruction -> - instruction.getReference()?.type == returnType - } - } - -fun MutableMethod.getTargetIndexWithFieldReferenceTypeReversed( - startIndex: Int, - returnType: String -): Int { - for (index in startIndex downTo 0) { - val instruction = getInstruction(index) - if (instruction.getReference()?.type != returnType) - continue - - return index - } - return -1 -} - -fun Method.getTargetIndexWithMethodReferenceName(methodName: String) = implementation?.let { - it.instructions.indexOfFirst { instruction -> - instruction.getReference()?.name == methodName - } -} ?: -1 - -fun MutableMethod.getTargetIndexWithMethodReferenceNameReversed(methodName: String) = - getTargetIndexWithMethodReferenceNameReversed( - implementation!!.instructions.size - 1, - methodName - ) - - -fun MutableMethod.getTargetIndexWithMethodReferenceName(startIndex: Int, methodName: String) = - implementation!!.instructions.let { - startIndex + it.subList(startIndex, it.size - 1).indexOfFirst { instruction -> - instruction.getReference()?.name == methodName - } - } - -fun MutableMethod.getTargetIndexWithMethodReferenceNameReversed( - startIndex: Int, - methodName: String -): Int { - for (index in startIndex downTo 0) { - val instruction = getInstruction(index) - if (instruction.getReference()?.name != methodName) - continue - - return index - } - return -1 -} - -fun Method.getTargetIndexWithReference(reference: String) = implementation?.let { - it.instructions.indexOfFirst { instruction -> - (instruction as? ReferenceInstruction)?.reference.toString().contains(reference) - } -} ?: -1 - -fun MutableMethod.getTargetIndexWithReference(reference: String) = - getTargetIndexWithReference(0, reference) - -fun MutableMethod.getTargetIndexWithReferenceReversed(reference: String) = - getTargetIndexWithReferenceReversed(implementation!!.instructions.size - 1, reference) - -fun MutableMethod.getTargetIndexWithReference(startIndex: Int, reference: String) = - implementation!!.instructions.let { - startIndex + it.subList(startIndex, it.size - 1).indexOfFirst { instruction -> - (instruction as? ReferenceInstruction)?.reference.toString().contains(reference) - } - } - -fun MutableMethod.getTargetIndexWithReferenceReversed(startIndex: Int, reference: String): Int { - for (index in startIndex downTo 0) { - val instruction = getInstruction(index) - if (!(instruction as? ReferenceInstruction)?.reference.toString().contains(reference)) - continue - - return index - } - return -1 -} - fun MethodFingerprintResult.getWalkerMethod(context: BytecodeContext, offset: Int) = mutableMethod.getWalkerMethod(context, offset) /** - * MethodWalker structural limitations cause incorrect class to be found - * - * MethodReference to find in YouTube 18.29.38: - * 'Lng;->d(Lou;)Z' - * - * Class found by MethodWalker in YouTube 18.29.38: - * 'Lcom/google/android/gms/maps/model/LatLng;' - * - * The reason this error occurs is because [BytecodeContext.findClass] checks whether className is included or not - * - * In ReVanced Patcher 19.3.1: - * fun findClass(className: String) = findClass { it.type.contains(className) } - * - * (Class 'Lcom/google/android/gms/maps/model/LatLng;' is returned because class 'Lcom/google/android/gms/maps/model/LatLng;' contains keyword 'Lng;') + * MethodWalker can find the wrong class: + * https://github.com/ReVanced/revanced-patcher/issues/309 * * As a workaround, redefine MethodWalker here */ fun MutableMethod.getWalkerMethod(context: BytecodeContext, offset: Int): MutableMethod { val newMethod = getInstruction(offset).reference as MethodReference - return context.findClass { classDef -> classDef.type == newMethod.definingClass } - ?.mutableClass - ?.methods - ?.first { method -> MethodUtil.methodSignaturesMatch(method, newMethod) } - ?: throw PatchException("This method can not be walked at offset $offset inside the method $name") + return context.findMethodOrThrow(newMethod.definingClass) { + MethodUtil.methodSignaturesMatch(this, newMethod) + } } -fun MutableClass.addFieldAndInstructions( - context: BytecodeContext, +fun BytecodeContext.addStaticFieldToIntegration( + className: String, methodName: String, fieldName: String, objectClass: String, smaliInstructions: String, - shouldAddConstructor: Boolean + shouldAddConstructor: Boolean = true ) { - val objectCall = "$this->$fieldName:$objectClass" - - methods.single { method -> method.name == methodName }.apply { - staticFields.add( - ImmutableField( - definingClass, - fieldName, - objectClass, - AccessFlags.PUBLIC or AccessFlags.STATIC, - null, - annotations, - null - ).toMutable() - ) + val mutableClass = findClass { classDef -> classDef.type == className } + ?.mutableClass + ?: throw PatchException("No matching classes found: $className") + + val objectCall = "$mutableClass->$fieldName:$objectClass" + + mutableClass.apply { + methods.first { method -> method.name == methodName }.apply { + staticFields.add( + ImmutableField( + definingClass, + fieldName, + objectClass, + AccessFlags.PUBLIC or AccessFlags.STATIC, + null, + annotations, + null + ).toMutable() + ) - addInstructionsWithLabels( - 0, - """ + addInstructionsWithLabels( + 0, + """ sget-object v0, $objectCall """ + smaliInstructions - ) + ) + } } - if (shouldAddConstructor) { - context.findClass(objectClass)!!.mutableClass.methods - .filter { method -> method.name == "" } - .forEach { mutableMethod -> - mutableMethod.apply { - val initializeIndex = indexOfFirstInstructionOrThrow { - opcode == Opcode.INVOKE_DIRECT && getReference()?.name == "" - } - val insertIndex = if (initializeIndex == -1) - 1 - else - initializeIndex + 1 - - val initializeRegister = if (initializeIndex == -1) - "p0" - else - "v${getInstruction(initializeIndex).registerC}" - - addInstruction( - insertIndex, - "sput-object $initializeRegister, $objectCall" - ) + if (!shouldAddConstructor) return + + findMethodsOrThrow(objectClass) + .filter { method -> MethodUtil.isConstructor(method) } + .forEach { mutableMethod -> + mutableMethod.apply { + val initializeIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_DIRECT && + getReference()?.name == "" } + val insertIndex = if (initializeIndex == -1) + 1 + else + initializeIndex + 1 + + val initializeRegister = if (initializeIndex == -1) + "p0" + else + "v${getInstruction(initializeIndex).registerC}" + + addInstruction( + insertIndex, + "sput-object $initializeRegister, $objectCall" + ) } + } +} + +fun BytecodeContext.findMethodOrThrow( + reference: String, + methodPredicate: Method.() -> Boolean = { MethodUtil.isConstructor(this) } +) = findMethodsOrThrow(reference).first(methodPredicate) + +fun BytecodeContext.findMethodsOrThrow(reference: String): MutableSet { + val methods = + findClass { classDef -> classDef.type == reference } + ?.mutableClass + ?.methods + + if (methods != null) { + return methods + } else { + throw PatchException("No matching methods found in: $reference") } } fun BytecodeContext.updatePatchStatus( className: String, methodName: String -) { - this.classes.forEach { classDef -> - if (classDef.type.endsWith(className)) { - val patchStatusMethod = - this.proxy(classDef).mutableClass.methods.first { it.name == methodName } - - patchStatusMethod.replaceInstruction( - 0, - "const/4 v0, 0x1" - ) - } - } -} +) = findMethodOrThrow(className) { name == methodName } + .replaceInstruction( + 0, + "const/4 v0, 0x1" + ) /** * Return the resolved methods of [MethodFingerprint]s early. @@ -832,7 +592,7 @@ fun List.returnEarly(bool: Boolean = false) { return v0 """ - else -> throw Exception("This case should never happen.") + else -> throw PatchException("This case should never happen: ${fingerprint.javaClass.simpleName}") } result.mutableMethod.addInstructions(0, stringInstructions) diff --git a/src/main/kotlin/app/revanced/util/ResourceUtils.kt b/src/main/kotlin/app/revanced/util/ResourceUtils.kt index d159536e0..52e7a5e86 100644 --- a/src/main/kotlin/app/revanced/util/ResourceUtils.kt +++ b/src/main/kotlin/app/revanced/util/ResourceUtils.kt @@ -8,6 +8,7 @@ import app.revanced.patcher.patch.options.PatchOption import app.revanced.patcher.util.DomFileEditor import org.w3c.dom.Element import org.w3c.dom.Node +import org.w3c.dom.NodeList import java.io.File import java.io.InputStream import java.nio.file.Files @@ -240,3 +241,29 @@ fun String.copyXmlNode(source: DomFileEditor, target: DomFileEditor): AutoClosea target.close() } } + +internal fun NodeList.findElementByAttributeValue(attributeName: String, value: String): Element? { + for (i in 0 until length) { + val node = item(i) + if (node.nodeType == Node.ELEMENT_NODE) { + val element = node as Element + + if (element.getAttribute(attributeName) == value) { + return element + } + + // Recursively search. + val found = element.childNodes.findElementByAttributeValue(attributeName, value) + if (found != null) { + return found + } + } + } + + return null +} + +internal fun NodeList.findElementByAttributeValueOrThrow(attributeName: String, value: String): Element { + return findElementByAttributeValue(attributeName, value) + ?: throw PatchException("Could not find: $attributeName $value") +} diff --git a/src/main/kotlin/app/revanced/util/fingerprint/LiteralValueFingerprint.kt b/src/main/kotlin/app/revanced/util/fingerprint/LiteralValueFingerprint.kt index 293855da4..ea7cf3ebb 100644 --- a/src/main/kotlin/app/revanced/util/fingerprint/LiteralValueFingerprint.kt +++ b/src/main/kotlin/app/revanced/util/fingerprint/LiteralValueFingerprint.kt @@ -1,7 +1,7 @@ package app.revanced.util.fingerprint import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.Opcode /** @@ -29,6 +29,6 @@ abstract class LiteralValueFingerprint( opcodes = opcodes, strings = strings, customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(literalSupplier()) + methodDef.containsWideLiteralInstructionValue(literalSupplier()) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/util/fingerprint/MethodReferenceNameFingerprint.kt b/src/main/kotlin/app/revanced/util/fingerprint/MethodReferenceNameFingerprint.kt deleted file mode 100644 index f2252f881..000000000 --- a/src/main/kotlin/app/revanced/util/fingerprint/MethodReferenceNameFingerprint.kt +++ /dev/null @@ -1,34 +0,0 @@ -package app.revanced.util.fingerprint - -import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.containsMethodReferenceNameInstructionIndex -import com.android.tools.smali.dexlib2.Opcode - -/** - * A fingerprint to resolve methods that contain a specific method reference name value. - * - * @param returnType The method's return type compared using String.startsWith. - * @param accessFlags The method's exact access flags using values of AccessFlags. - * @param parameters The parameters of the method. Partial matches allowed and follow the same rules as returnType. - * @param opcodes An opcode pattern of the method's instructions. Wildcard or unknown opcodes can be specified by null. - * @param strings A list of the method's strings compared each using String.contains. - * @param reference A supplier for the method reference name value to check for. - */ -abstract class MethodReferenceNameFingerprint( - returnType: String? = null, - accessFlags: Int? = null, - parameters: Iterable? = null, - opcodes: Iterable? = null, - strings: Iterable? = null, - // Has to be a supplier because the fingerprint is created before patches can check reference. - reference: () -> String -) : MethodFingerprint( - returnType = returnType, - accessFlags = accessFlags, - parameters = parameters, - opcodes = opcodes, - strings = strings, - customFingerprint = { methodDef, _ -> - methodDef.containsMethodReferenceNameInstructionIndex(reference()) - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/util/fingerprint/MultiMethodFingerprint.kt b/src/main/kotlin/app/revanced/util/fingerprint/MultiMethodFingerprint.kt new file mode 100644 index 000000000..b25b53876 --- /dev/null +++ b/src/main/kotlin/app/revanced/util/fingerprint/MultiMethodFingerprint.kt @@ -0,0 +1,208 @@ +package app.revanced.util.fingerprint + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprintResult +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.ClassDef +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.reference.StringReference + +private typealias StringMatch = MethodFingerprintResult.MethodFingerprintScanResult.StringsScanResult.StringMatch +private typealias StringsScanResult = MethodFingerprintResult.MethodFingerprintScanResult.StringsScanResult + +/** + * Represents the [MethodFingerprint] for a method. + * @param returnType The return type of the method. + * @param accessFlags The access flags of the method. + * @param parameters The parameters of the method. + * @param opcodes The list of opcodes of the method. + * @param strings A list of strings which a method contains. + * @param customFingerprint A custom condition for this fingerprint. + * A `null` opcode is equals to an unknown opcode. + */ +abstract class MultiMethodFingerprint( + val returnType: String? = null, + val accessFlags: Int? = null, + val parameters: Iterable? = null, + val opcodes: Iterable? = null, + val strings: Iterable? = null, + val customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null +) { + /** + * The result of the [MethodFingerprint]. + */ + var result = mutableListOf() + private var resolved = false + + companion object { + /** + * Resolve a list of [MethodFingerprint] against a list of [ClassDef]. + * + * @param classes The classes on which to resolve the [MethodFingerprint] in. + * @param context The [BytecodeContext] to host proxies. + * @return True if the resolution was successful, false otherwise. + */ + fun Iterable.resolve( + context: BytecodeContext, + classes: Iterable + ) { + for (fingerprint in this) { // For each fingerprint + if (fingerprint.resolved) continue + for (classDef in classes) // search through all classes for the fingerprint + fingerprint.resolve(context, classDef) + fingerprint.resolved = true + } + } + + /** + * Resolve a [MethodFingerprint] against a [ClassDef]. + * + * @param forClass The class on which to resolve the [MethodFingerprint] in. + * @param context The [BytecodeContext] to host proxies. + * @return True if the resolution was successful, false otherwise. + */ + fun MultiMethodFingerprint.resolve(context: BytecodeContext, forClass: ClassDef): Boolean { + for (method in forClass.methods) + if (this.resolve(context, method, forClass)) + return true + return false + } + + /** + * Resolve a [MethodFingerprint] against a [Method]. + * + * @param method The class on which to resolve the [MethodFingerprint] in. + * @param forClass The class on which to resolve the [MethodFingerprint]. + * @param context The [BytecodeContext] to host proxies. + * @return True if the resolution was successful or if the fingerprint is already resolved, false otherwise. + */ + fun MultiMethodFingerprint.resolve( + context: BytecodeContext, + method: Method, + forClass: ClassDef + ): Boolean { + val methodFingerprint = this + + if (methodFingerprint.returnType != null && !method.returnType.startsWith( + methodFingerprint.returnType + ) + ) + return false + + if (methodFingerprint.accessFlags != null && methodFingerprint.accessFlags != method.accessFlags) + return false + + fun parametersEqual( + parameters1: Iterable, parameters2: Iterable + ): Boolean { + if (parameters1.count() != parameters2.count()) return false + val iterator1 = parameters1.iterator() + parameters2.forEach { + if (!it.startsWith(iterator1.next())) return false + } + return true + } + + if (methodFingerprint.parameters != null && !parametersEqual( + methodFingerprint.parameters, // TODO: parseParameters() + method.parameterTypes + ) + ) return false + + @Suppress("UNNECESSARY_NOT_NULL_ASSERTION") + if (methodFingerprint.customFingerprint != null && !methodFingerprint.customFingerprint!!( + method, + forClass + ) + ) + return false + + val stringsScanResult = if (methodFingerprint.strings != null) { + StringsScanResult( + buildList { + val implementation = method.implementation ?: return false + + val stringsList = methodFingerprint.strings.toMutableList() + + implementation.instructions.forEachIndexed { instructionIndex, instruction -> + if ( + instruction.opcode != Opcode.CONST_STRING && + instruction.opcode != Opcode.CONST_STRING_JUMBO + ) return@forEachIndexed + + val string = + ((instruction as ReferenceInstruction).reference as StringReference).string + val index = stringsList.indexOfFirst(string::contains) + if (index == -1) return@forEachIndexed + + add(StringMatch(string, instructionIndex)) + stringsList.removeAt(index) + } + + if (stringsList.isNotEmpty()) return false + } + ) + } else null + + val patternScanResult = if (methodFingerprint.opcodes != null) { + method.implementation?.instructions ?: return false + + method.patternScan(methodFingerprint) ?: return false + } else null + + methodFingerprint.result.add( + MethodFingerprintResult( + method, + forClass, + MethodFingerprintResult.MethodFingerprintScanResult( + patternScanResult, + stringsScanResult + ), + context + ) + ) + + return true + } + + private fun Method.patternScan( + fingerprint: MultiMethodFingerprint + ): MethodFingerprintResult.MethodFingerprintScanResult.PatternScanResult? { + val instructions = this.implementation!!.instructions + + val pattern = fingerprint.opcodes!! + val instructionLength = instructions.count() + val patternLength = pattern.count() + + for (index in 0 until instructionLength) { + var patternIndex = 0 + + while (index + patternIndex < instructionLength) { + val originalOpcode = instructions.elementAt(index + patternIndex).opcode + val patternOpcode = pattern.elementAt(patternIndex) + + if (patternOpcode != null && patternOpcode.ordinal != originalOpcode.ordinal) { + // reaching maximum threshold (0) means, + // the pattern does not match to the current instructions + break + } + + if (patternIndex < patternLength - 1) { + // if the entire pattern has not been scanned yet + // continue the scan + patternIndex++ + continue + } + return MethodFingerprintResult.MethodFingerprintScanResult.PatternScanResult( + index, + index + patternIndex + ) + } + } + + return null + } + } +} diff --git a/src/main/kotlin/app/revanced/util/fingerprint/ReferenceFingerprint.kt b/src/main/kotlin/app/revanced/util/fingerprint/ReferenceFingerprint.kt deleted file mode 100644 index 69cb6b057..000000000 --- a/src/main/kotlin/app/revanced/util/fingerprint/ReferenceFingerprint.kt +++ /dev/null @@ -1,34 +0,0 @@ -package app.revanced.util.fingerprint - -import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.containsReferenceInstructionIndex -import com.android.tools.smali.dexlib2.Opcode - -/** - * A fingerprint to resolve methods that contain a specific reference value. - * - * @param returnType The method's return type compared using String.startsWith. - * @param accessFlags The method's exact access flags using values of AccessFlags. - * @param parameters The parameters of the method. Partial matches allowed and follow the same rules as returnType. - * @param opcodes An opcode pattern of the method's instructions. Wildcard or unknown opcodes can be specified by null. - * @param strings A list of the method's strings compared each using String.contains. - * @param reference A supplier for the reference value to check for. - */ -abstract class ReferenceFingerprint( - returnType: String? = null, - accessFlags: Int? = null, - parameters: Iterable? = null, - opcodes: Iterable? = null, - strings: Iterable? = null, - // Has to be a supplier because the fingerprint is created before patches can check reference. - reference: () -> String -) : MethodFingerprint( - returnType = returnType, - accessFlags = accessFlags, - parameters = parameters, - opcodes = opcodes, - strings = strings, - customFingerprint = { methodDef, _ -> - methodDef.containsReferenceInstructionIndex(reference()) - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/util/patch/MultiMethodBytecodePatch.kt b/src/main/kotlin/app/revanced/util/patch/MultiMethodBytecodePatch.kt new file mode 100644 index 000000000..fa137319a --- /dev/null +++ b/src/main/kotlin/app/revanced/util/patch/MultiMethodBytecodePatch.kt @@ -0,0 +1,16 @@ +package app.revanced.util.patch + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.util.fingerprint.MultiMethodFingerprint +import app.revanced.util.fingerprint.MultiMethodFingerprint.Companion.resolve + +abstract class MultiMethodBytecodePatch( + val fingerprints: Set = setOf(), + val multiFingerprints: Set = setOf() +) : BytecodePatch(fingerprints) { + override fun execute(context: BytecodeContext) { + multiFingerprints.resolve(context, context.classes) + } +} diff --git a/src/main/resources/music/branding/mmt_orange/header/drawable-hdpi/action_bar_logo.png b/src/main/resources/music/branding/mmt_orange/header/drawable-hdpi/action_bar_logo.png new file mode 100644 index 000000000..f4e48f438 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/header/drawable-hdpi/action_bar_logo.png differ diff --git a/src/main/resources/music/branding/mmt_orange/header/drawable-hdpi/logo_music.png b/src/main/resources/music/branding/mmt_orange/header/drawable-hdpi/logo_music.png new file mode 100644 index 000000000..1be6cf1e2 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/header/drawable-hdpi/logo_music.png differ diff --git a/src/main/resources/music/branding/mmt_orange/header/drawable-hdpi/ytm_logo.png b/src/main/resources/music/branding/mmt_orange/header/drawable-hdpi/ytm_logo.png new file mode 100644 index 000000000..773cb809f Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/header/drawable-hdpi/ytm_logo.png differ diff --git a/src/main/resources/music/branding/mmt_orange/header/drawable-mdpi/action_bar_logo.png b/src/main/resources/music/branding/mmt_orange/header/drawable-mdpi/action_bar_logo.png new file mode 100644 index 000000000..c1de1ce0e Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/header/drawable-mdpi/action_bar_logo.png differ diff --git a/src/main/resources/music/branding/mmt_orange/header/drawable-mdpi/logo_music.png b/src/main/resources/music/branding/mmt_orange/header/drawable-mdpi/logo_music.png new file mode 100644 index 000000000..d2f57301d Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/header/drawable-mdpi/logo_music.png differ diff --git a/src/main/resources/music/branding/mmt_orange/header/drawable-mdpi/ytm_logo.png b/src/main/resources/music/branding/mmt_orange/header/drawable-mdpi/ytm_logo.png new file mode 100644 index 000000000..95abcc84b Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/header/drawable-mdpi/ytm_logo.png differ diff --git a/src/main/resources/music/branding/mmt_orange/header/drawable-xhdpi/action_bar_logo.png b/src/main/resources/music/branding/mmt_orange/header/drawable-xhdpi/action_bar_logo.png new file mode 100644 index 000000000..02bde6ac6 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/header/drawable-xhdpi/action_bar_logo.png differ diff --git a/src/main/resources/music/branding/mmt_orange/header/drawable-xhdpi/logo_music.png b/src/main/resources/music/branding/mmt_orange/header/drawable-xhdpi/logo_music.png new file mode 100644 index 000000000..4d0d9ba97 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/header/drawable-xhdpi/logo_music.png differ diff --git a/src/main/resources/music/branding/mmt_orange/header/drawable-xhdpi/ytm_logo.png b/src/main/resources/music/branding/mmt_orange/header/drawable-xhdpi/ytm_logo.png new file mode 100644 index 000000000..377eb8fbe Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/header/drawable-xhdpi/ytm_logo.png differ diff --git a/src/main/resources/music/branding/mmt_orange/header/drawable-xxhdpi/action_bar_logo.png b/src/main/resources/music/branding/mmt_orange/header/drawable-xxhdpi/action_bar_logo.png new file mode 100644 index 000000000..b53c7ba11 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/header/drawable-xxhdpi/action_bar_logo.png differ diff --git a/src/main/resources/music/branding/mmt_orange/header/drawable-xxhdpi/logo_music.png b/src/main/resources/music/branding/mmt_orange/header/drawable-xxhdpi/logo_music.png new file mode 100644 index 000000000..7814159c0 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/header/drawable-xxhdpi/logo_music.png differ diff --git a/src/main/resources/music/branding/mmt_orange/header/drawable-xxhdpi/ytm_logo.png b/src/main/resources/music/branding/mmt_orange/header/drawable-xxhdpi/ytm_logo.png new file mode 100644 index 000000000..377eb8fbe Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/header/drawable-xxhdpi/ytm_logo.png differ diff --git a/src/main/resources/music/branding/mmt_orange/header/drawable-xxxhdpi/action_bar_logo.png b/src/main/resources/music/branding/mmt_orange/header/drawable-xxxhdpi/action_bar_logo.png new file mode 100644 index 000000000..9992f0c84 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/header/drawable-xxxhdpi/action_bar_logo.png differ diff --git a/src/main/resources/music/branding/mmt_orange/header/drawable-xxxhdpi/logo_music.png b/src/main/resources/music/branding/mmt_orange/header/drawable-xxxhdpi/logo_music.png new file mode 100644 index 000000000..fcfb8d5bf Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/header/drawable-xxxhdpi/logo_music.png differ diff --git a/src/main/resources/music/branding/mmt_orange/header/drawable-xxxhdpi/ytm_logo.png b/src/main/resources/music/branding/mmt_orange/header/drawable-xxxhdpi/ytm_logo.png new file mode 100644 index 000000000..6cab734f6 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/header/drawable-xxxhdpi/ytm_logo.png differ diff --git a/src/main/resources/music/branding/mmt_orange/launcher/mipmap-hdpi/adaptiveproduct_youtube_music_background_color_108.png b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-hdpi/adaptiveproduct_youtube_music_background_color_108.png new file mode 100644 index 000000000..129276322 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-hdpi/adaptiveproduct_youtube_music_background_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_orange/launcher/mipmap-hdpi/adaptiveproduct_youtube_music_foreground_color_108.png b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-hdpi/adaptiveproduct_youtube_music_foreground_color_108.png new file mode 100644 index 000000000..74b731fa3 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-hdpi/adaptiveproduct_youtube_music_foreground_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_orange/launcher/mipmap-hdpi/ic_launcher_release.png b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-hdpi/ic_launcher_release.png new file mode 100644 index 000000000..a7eb92041 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-hdpi/ic_launcher_release.png differ diff --git a/src/main/resources/music/branding/mmt_orange/launcher/mipmap-mdpi/adaptiveproduct_youtube_music_background_color_108.png b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-mdpi/adaptiveproduct_youtube_music_background_color_108.png new file mode 100644 index 000000000..8a6252836 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-mdpi/adaptiveproduct_youtube_music_background_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_orange/launcher/mipmap-mdpi/adaptiveproduct_youtube_music_foreground_color_108.png b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-mdpi/adaptiveproduct_youtube_music_foreground_color_108.png new file mode 100644 index 000000000..99d1b7421 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-mdpi/adaptiveproduct_youtube_music_foreground_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_orange/launcher/mipmap-mdpi/ic_launcher_release.png b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-mdpi/ic_launcher_release.png new file mode 100644 index 000000000..237498d33 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-mdpi/ic_launcher_release.png differ diff --git a/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xhdpi/adaptiveproduct_youtube_music_background_color_108.png b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xhdpi/adaptiveproduct_youtube_music_background_color_108.png new file mode 100644 index 000000000..a95aff113 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xhdpi/adaptiveproduct_youtube_music_background_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xhdpi/adaptiveproduct_youtube_music_foreground_color_108.png b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xhdpi/adaptiveproduct_youtube_music_foreground_color_108.png new file mode 100644 index 000000000..9f350554a Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xhdpi/adaptiveproduct_youtube_music_foreground_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xhdpi/ic_launcher_release.png b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xhdpi/ic_launcher_release.png new file mode 100644 index 000000000..fc779f3e8 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xhdpi/ic_launcher_release.png differ diff --git a/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_music_background_color_108.png b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_music_background_color_108.png new file mode 100644 index 000000000..d6cec4cce Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_music_background_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_music_foreground_color_108.png b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_music_foreground_color_108.png new file mode 100644 index 000000000..095244242 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_music_foreground_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xxhdpi/ic_launcher_release.png b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xxhdpi/ic_launcher_release.png new file mode 100644 index 000000000..8a82c833d Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xxhdpi/ic_launcher_release.png differ diff --git a/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_music_background_color_108.png b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_music_background_color_108.png new file mode 100644 index 000000000..6ef5ac482 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_music_background_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_music_foreground_color_108.png b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_music_foreground_color_108.png new file mode 100644 index 000000000..50a312db3 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_music_foreground_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xxxhdpi/ic_launcher_release.png b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xxxhdpi/ic_launcher_release.png new file mode 100644 index 000000000..746b81549 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/launcher/mipmap-xxxhdpi/ic_launcher_release.png differ diff --git a/src/main/resources/music/branding/mmt_orange/monochrome/drawable/ic_app_icons_themed_youtube_music.xml b/src/main/resources/music/branding/mmt_orange/monochrome/drawable/ic_app_icons_themed_youtube_music.xml new file mode 100644 index 000000000..e1fdba50d --- /dev/null +++ b/src/main/resources/music/branding/mmt_orange/monochrome/drawable/ic_app_icons_themed_youtube_music.xml @@ -0,0 +1,13 @@ + + + diff --git a/src/main/resources/music/branding/mmt_orange/settings/drawable/revanced_extended_settings_key_icon.xml b/src/main/resources/music/branding/mmt_orange/settings/drawable/revanced_extended_settings_key_icon.xml new file mode 100755 index 000000000..085386494 --- /dev/null +++ b/src/main/resources/music/branding/mmt_orange/settings/drawable/revanced_extended_settings_key_icon.xml @@ -0,0 +1,1038 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/music/branding/mmt_orange/splash/drawable-hdpi/action_bar_logo_release.png b/src/main/resources/music/branding/mmt_orange/splash/drawable-hdpi/action_bar_logo_release.png new file mode 100644 index 000000000..3e8f95fe0 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/splash/drawable-hdpi/action_bar_logo_release.png differ diff --git a/src/main/resources/music/branding/mmt_orange/splash/drawable-hdpi/record.png b/src/main/resources/music/branding/mmt_orange/splash/drawable-hdpi/record.png new file mode 100644 index 000000000..2c6295a43 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/splash/drawable-hdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_orange/splash/drawable-large-hdpi/record.png b/src/main/resources/music/branding/mmt_orange/splash/drawable-large-hdpi/record.png new file mode 100644 index 000000000..1774b3356 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/splash/drawable-large-hdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_orange/splash/drawable-large-mdpi/record.png b/src/main/resources/music/branding/mmt_orange/splash/drawable-large-mdpi/record.png new file mode 100644 index 000000000..f8eb1993b Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/splash/drawable-large-mdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_orange/splash/drawable-large-xhdpi/record.png b/src/main/resources/music/branding/mmt_orange/splash/drawable-large-xhdpi/record.png new file mode 100644 index 000000000..8ca7861b2 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/splash/drawable-large-xhdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_orange/splash/drawable-mdpi/record.png b/src/main/resources/music/branding/mmt_orange/splash/drawable-mdpi/record.png new file mode 100644 index 000000000..30dbc3d7f Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/splash/drawable-mdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_orange/splash/drawable-xhdpi/record.png b/src/main/resources/music/branding/mmt_orange/splash/drawable-xhdpi/record.png new file mode 100644 index 000000000..0d04a49d9 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/splash/drawable-xhdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_orange/splash/drawable-xlarge-hdpi/record.png b/src/main/resources/music/branding/mmt_orange/splash/drawable-xlarge-hdpi/record.png new file mode 100644 index 000000000..1c84d459a Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/splash/drawable-xlarge-hdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_orange/splash/drawable-xlarge-mdpi/record.png b/src/main/resources/music/branding/mmt_orange/splash/drawable-xlarge-mdpi/record.png new file mode 100644 index 000000000..0d04a49d9 Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/splash/drawable-xlarge-mdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_orange/splash/drawable-xxhdpi/record.png b/src/main/resources/music/branding/mmt_orange/splash/drawable-xxhdpi/record.png new file mode 100644 index 000000000..1c84d459a Binary files /dev/null and b/src/main/resources/music/branding/mmt_orange/splash/drawable-xxhdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_pink/header/drawable-hdpi/action_bar_logo.png b/src/main/resources/music/branding/mmt_pink/header/drawable-hdpi/action_bar_logo.png new file mode 100644 index 000000000..f2e724259 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/header/drawable-hdpi/action_bar_logo.png differ diff --git a/src/main/resources/music/branding/mmt_pink/header/drawable-hdpi/logo_music.png b/src/main/resources/music/branding/mmt_pink/header/drawable-hdpi/logo_music.png new file mode 100644 index 000000000..c5fb9a612 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/header/drawable-hdpi/logo_music.png differ diff --git a/src/main/resources/music/branding/mmt_pink/header/drawable-hdpi/ytm_logo.png b/src/main/resources/music/branding/mmt_pink/header/drawable-hdpi/ytm_logo.png new file mode 100644 index 000000000..773cb809f Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/header/drawable-hdpi/ytm_logo.png differ diff --git a/src/main/resources/music/branding/mmt_pink/header/drawable-mdpi/action_bar_logo.png b/src/main/resources/music/branding/mmt_pink/header/drawable-mdpi/action_bar_logo.png new file mode 100644 index 000000000..b9c222e2d Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/header/drawable-mdpi/action_bar_logo.png differ diff --git a/src/main/resources/music/branding/mmt_pink/header/drawable-mdpi/logo_music.png b/src/main/resources/music/branding/mmt_pink/header/drawable-mdpi/logo_music.png new file mode 100644 index 000000000..0f4ed4802 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/header/drawable-mdpi/logo_music.png differ diff --git a/src/main/resources/music/branding/mmt_pink/header/drawable-mdpi/ytm_logo.png b/src/main/resources/music/branding/mmt_pink/header/drawable-mdpi/ytm_logo.png new file mode 100644 index 000000000..95abcc84b Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/header/drawable-mdpi/ytm_logo.png differ diff --git a/src/main/resources/music/branding/mmt_pink/header/drawable-xhdpi/action_bar_logo.png b/src/main/resources/music/branding/mmt_pink/header/drawable-xhdpi/action_bar_logo.png new file mode 100644 index 000000000..34c54379f Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/header/drawable-xhdpi/action_bar_logo.png differ diff --git a/src/main/resources/music/branding/mmt_pink/header/drawable-xhdpi/logo_music.png b/src/main/resources/music/branding/mmt_pink/header/drawable-xhdpi/logo_music.png new file mode 100644 index 000000000..b4570cd9c Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/header/drawable-xhdpi/logo_music.png differ diff --git a/src/main/resources/music/branding/mmt_pink/header/drawable-xhdpi/ytm_logo.png b/src/main/resources/music/branding/mmt_pink/header/drawable-xhdpi/ytm_logo.png new file mode 100644 index 000000000..377eb8fbe Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/header/drawable-xhdpi/ytm_logo.png differ diff --git a/src/main/resources/music/branding/mmt_pink/header/drawable-xxhdpi/action_bar_logo.png b/src/main/resources/music/branding/mmt_pink/header/drawable-xxhdpi/action_bar_logo.png new file mode 100644 index 000000000..cebf6fb51 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/header/drawable-xxhdpi/action_bar_logo.png differ diff --git a/src/main/resources/music/branding/mmt_pink/header/drawable-xxhdpi/logo_music.png b/src/main/resources/music/branding/mmt_pink/header/drawable-xxhdpi/logo_music.png new file mode 100644 index 000000000..b6edcef88 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/header/drawable-xxhdpi/logo_music.png differ diff --git a/src/main/resources/music/branding/mmt_pink/header/drawable-xxhdpi/ytm_logo.png b/src/main/resources/music/branding/mmt_pink/header/drawable-xxhdpi/ytm_logo.png new file mode 100644 index 000000000..377eb8fbe Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/header/drawable-xxhdpi/ytm_logo.png differ diff --git a/src/main/resources/music/branding/mmt_pink/header/drawable-xxxhdpi/action_bar_logo.png b/src/main/resources/music/branding/mmt_pink/header/drawable-xxxhdpi/action_bar_logo.png new file mode 100644 index 000000000..a9f8e0f44 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/header/drawable-xxxhdpi/action_bar_logo.png differ diff --git a/src/main/resources/music/branding/mmt_pink/header/drawable-xxxhdpi/logo_music.png b/src/main/resources/music/branding/mmt_pink/header/drawable-xxxhdpi/logo_music.png new file mode 100644 index 000000000..032357bdc Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/header/drawable-xxxhdpi/logo_music.png differ diff --git a/src/main/resources/music/branding/mmt_pink/header/drawable-xxxhdpi/ytm_logo.png b/src/main/resources/music/branding/mmt_pink/header/drawable-xxxhdpi/ytm_logo.png new file mode 100644 index 000000000..6cab734f6 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/header/drawable-xxxhdpi/ytm_logo.png differ diff --git a/src/main/resources/music/branding/mmt_pink/launcher/mipmap-hdpi/adaptiveproduct_youtube_music_background_color_108.png b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-hdpi/adaptiveproduct_youtube_music_background_color_108.png new file mode 100644 index 000000000..129276322 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-hdpi/adaptiveproduct_youtube_music_background_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_pink/launcher/mipmap-hdpi/adaptiveproduct_youtube_music_foreground_color_108.png b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-hdpi/adaptiveproduct_youtube_music_foreground_color_108.png new file mode 100644 index 000000000..456447add Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-hdpi/adaptiveproduct_youtube_music_foreground_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_pink/launcher/mipmap-hdpi/ic_launcher_release.png b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-hdpi/ic_launcher_release.png new file mode 100644 index 000000000..0e634430e Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-hdpi/ic_launcher_release.png differ diff --git a/src/main/resources/music/branding/mmt_pink/launcher/mipmap-mdpi/adaptiveproduct_youtube_music_background_color_108.png b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-mdpi/adaptiveproduct_youtube_music_background_color_108.png new file mode 100644 index 000000000..8a6252836 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-mdpi/adaptiveproduct_youtube_music_background_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_pink/launcher/mipmap-mdpi/adaptiveproduct_youtube_music_foreground_color_108.png b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-mdpi/adaptiveproduct_youtube_music_foreground_color_108.png new file mode 100644 index 000000000..0657a7b0c Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-mdpi/adaptiveproduct_youtube_music_foreground_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_pink/launcher/mipmap-mdpi/ic_launcher_release.png b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-mdpi/ic_launcher_release.png new file mode 100644 index 000000000..8c85169be Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-mdpi/ic_launcher_release.png differ diff --git a/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xhdpi/adaptiveproduct_youtube_music_background_color_108.png b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xhdpi/adaptiveproduct_youtube_music_background_color_108.png new file mode 100644 index 000000000..a95aff113 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xhdpi/adaptiveproduct_youtube_music_background_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xhdpi/adaptiveproduct_youtube_music_foreground_color_108.png b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xhdpi/adaptiveproduct_youtube_music_foreground_color_108.png new file mode 100644 index 000000000..b3eea0d0d Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xhdpi/adaptiveproduct_youtube_music_foreground_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xhdpi/ic_launcher_release.png b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xhdpi/ic_launcher_release.png new file mode 100644 index 000000000..2dbde0492 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xhdpi/ic_launcher_release.png differ diff --git a/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_music_background_color_108.png b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_music_background_color_108.png new file mode 100644 index 000000000..d6cec4cce Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_music_background_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_music_foreground_color_108.png b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_music_foreground_color_108.png new file mode 100644 index 000000000..4f782df5f Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_music_foreground_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xxhdpi/ic_launcher_release.png b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xxhdpi/ic_launcher_release.png new file mode 100644 index 000000000..90e837721 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xxhdpi/ic_launcher_release.png differ diff --git a/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_music_background_color_108.png b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_music_background_color_108.png new file mode 100644 index 000000000..6ef5ac482 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_music_background_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_music_foreground_color_108.png b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_music_foreground_color_108.png new file mode 100644 index 000000000..f259a36ba Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_music_foreground_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xxxhdpi/ic_launcher_release.png b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xxxhdpi/ic_launcher_release.png new file mode 100644 index 000000000..f6fe8e3e2 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/launcher/mipmap-xxxhdpi/ic_launcher_release.png differ diff --git a/src/main/resources/music/branding/mmt_pink/monochrome/drawable/ic_app_icons_themed_youtube_music.xml b/src/main/resources/music/branding/mmt_pink/monochrome/drawable/ic_app_icons_themed_youtube_music.xml new file mode 100644 index 000000000..e1fdba50d --- /dev/null +++ b/src/main/resources/music/branding/mmt_pink/monochrome/drawable/ic_app_icons_themed_youtube_music.xml @@ -0,0 +1,13 @@ + + + diff --git a/src/main/resources/music/branding/mmt_pink/settings/drawable/revanced_extended_settings_key_icon.xml b/src/main/resources/music/branding/mmt_pink/settings/drawable/revanced_extended_settings_key_icon.xml new file mode 100755 index 000000000..c772d6c56 --- /dev/null +++ b/src/main/resources/music/branding/mmt_pink/settings/drawable/revanced_extended_settings_key_icon.xml @@ -0,0 +1,1038 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/music/branding/mmt_pink/splash/drawable-hdpi/action_bar_logo_release.png b/src/main/resources/music/branding/mmt_pink/splash/drawable-hdpi/action_bar_logo_release.png new file mode 100644 index 000000000..817836ce5 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/splash/drawable-hdpi/action_bar_logo_release.png differ diff --git a/src/main/resources/music/branding/mmt_pink/splash/drawable-hdpi/record.png b/src/main/resources/music/branding/mmt_pink/splash/drawable-hdpi/record.png new file mode 100644 index 000000000..92b6ba1ee Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/splash/drawable-hdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_pink/splash/drawable-large-hdpi/record.png b/src/main/resources/music/branding/mmt_pink/splash/drawable-large-hdpi/record.png new file mode 100644 index 000000000..03a6748d2 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/splash/drawable-large-hdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_pink/splash/drawable-large-mdpi/record.png b/src/main/resources/music/branding/mmt_pink/splash/drawable-large-mdpi/record.png new file mode 100644 index 000000000..08e70487b Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/splash/drawable-large-mdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_pink/splash/drawable-large-xhdpi/record.png b/src/main/resources/music/branding/mmt_pink/splash/drawable-large-xhdpi/record.png new file mode 100644 index 000000000..63646ce0e Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/splash/drawable-large-xhdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_pink/splash/drawable-mdpi/record.png b/src/main/resources/music/branding/mmt_pink/splash/drawable-mdpi/record.png new file mode 100644 index 000000000..d33676d94 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/splash/drawable-mdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_pink/splash/drawable-xhdpi/record.png b/src/main/resources/music/branding/mmt_pink/splash/drawable-xhdpi/record.png new file mode 100644 index 000000000..c8c77be01 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/splash/drawable-xhdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_pink/splash/drawable-xlarge-hdpi/record.png b/src/main/resources/music/branding/mmt_pink/splash/drawable-xlarge-hdpi/record.png new file mode 100644 index 000000000..a37e2fcf8 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/splash/drawable-xlarge-hdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_pink/splash/drawable-xlarge-mdpi/record.png b/src/main/resources/music/branding/mmt_pink/splash/drawable-xlarge-mdpi/record.png new file mode 100644 index 000000000..c8c77be01 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/splash/drawable-xlarge-mdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_pink/splash/drawable-xxhdpi/record.png b/src/main/resources/music/branding/mmt_pink/splash/drawable-xxhdpi/record.png new file mode 100644 index 000000000..a37e2fcf8 Binary files /dev/null and b/src/main/resources/music/branding/mmt_pink/splash/drawable-xxhdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/header/drawable-hdpi/action_bar_logo.png b/src/main/resources/music/branding/mmt_turquoise/header/drawable-hdpi/action_bar_logo.png new file mode 100644 index 000000000..24b413f64 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/header/drawable-hdpi/action_bar_logo.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/header/drawable-hdpi/logo_music.png b/src/main/resources/music/branding/mmt_turquoise/header/drawable-hdpi/logo_music.png new file mode 100644 index 000000000..ab9a78bcb Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/header/drawable-hdpi/logo_music.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/header/drawable-hdpi/ytm_logo.png b/src/main/resources/music/branding/mmt_turquoise/header/drawable-hdpi/ytm_logo.png new file mode 100644 index 000000000..773cb809f Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/header/drawable-hdpi/ytm_logo.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/header/drawable-mdpi/action_bar_logo.png b/src/main/resources/music/branding/mmt_turquoise/header/drawable-mdpi/action_bar_logo.png new file mode 100644 index 000000000..949968379 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/header/drawable-mdpi/action_bar_logo.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/header/drawable-mdpi/logo_music.png b/src/main/resources/music/branding/mmt_turquoise/header/drawable-mdpi/logo_music.png new file mode 100644 index 000000000..64766d436 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/header/drawable-mdpi/logo_music.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/header/drawable-mdpi/ytm_logo.png b/src/main/resources/music/branding/mmt_turquoise/header/drawable-mdpi/ytm_logo.png new file mode 100644 index 000000000..95abcc84b Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/header/drawable-mdpi/ytm_logo.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/header/drawable-xhdpi/action_bar_logo.png b/src/main/resources/music/branding/mmt_turquoise/header/drawable-xhdpi/action_bar_logo.png new file mode 100644 index 000000000..5d2102141 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/header/drawable-xhdpi/action_bar_logo.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/header/drawable-xhdpi/logo_music.png b/src/main/resources/music/branding/mmt_turquoise/header/drawable-xhdpi/logo_music.png new file mode 100644 index 000000000..035c0e01e Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/header/drawable-xhdpi/logo_music.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/header/drawable-xhdpi/ytm_logo.png b/src/main/resources/music/branding/mmt_turquoise/header/drawable-xhdpi/ytm_logo.png new file mode 100644 index 000000000..377eb8fbe Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/header/drawable-xhdpi/ytm_logo.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/header/drawable-xxhdpi/action_bar_logo.png b/src/main/resources/music/branding/mmt_turquoise/header/drawable-xxhdpi/action_bar_logo.png new file mode 100644 index 000000000..77338eee8 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/header/drawable-xxhdpi/action_bar_logo.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/header/drawable-xxhdpi/logo_music.png b/src/main/resources/music/branding/mmt_turquoise/header/drawable-xxhdpi/logo_music.png new file mode 100644 index 000000000..df8af881e Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/header/drawable-xxhdpi/logo_music.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/header/drawable-xxhdpi/ytm_logo.png b/src/main/resources/music/branding/mmt_turquoise/header/drawable-xxhdpi/ytm_logo.png new file mode 100644 index 000000000..377eb8fbe Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/header/drawable-xxhdpi/ytm_logo.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/header/drawable-xxxhdpi/action_bar_logo.png b/src/main/resources/music/branding/mmt_turquoise/header/drawable-xxxhdpi/action_bar_logo.png new file mode 100644 index 000000000..e504ee0b1 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/header/drawable-xxxhdpi/action_bar_logo.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/header/drawable-xxxhdpi/logo_music.png b/src/main/resources/music/branding/mmt_turquoise/header/drawable-xxxhdpi/logo_music.png new file mode 100644 index 000000000..f82372089 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/header/drawable-xxxhdpi/logo_music.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/header/drawable-xxxhdpi/ytm_logo.png b/src/main/resources/music/branding/mmt_turquoise/header/drawable-xxxhdpi/ytm_logo.png new file mode 100644 index 000000000..6cab734f6 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/header/drawable-xxxhdpi/ytm_logo.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-hdpi/adaptiveproduct_youtube_music_background_color_108.png b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-hdpi/adaptiveproduct_youtube_music_background_color_108.png new file mode 100644 index 000000000..129276322 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-hdpi/adaptiveproduct_youtube_music_background_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-hdpi/adaptiveproduct_youtube_music_foreground_color_108.png b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-hdpi/adaptiveproduct_youtube_music_foreground_color_108.png new file mode 100644 index 000000000..9f4eea693 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-hdpi/adaptiveproduct_youtube_music_foreground_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-hdpi/ic_launcher_release.png b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-hdpi/ic_launcher_release.png new file mode 100644 index 000000000..5d7d978b1 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-hdpi/ic_launcher_release.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-mdpi/adaptiveproduct_youtube_music_background_color_108.png b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-mdpi/adaptiveproduct_youtube_music_background_color_108.png new file mode 100644 index 000000000..8a6252836 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-mdpi/adaptiveproduct_youtube_music_background_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-mdpi/adaptiveproduct_youtube_music_foreground_color_108.png b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-mdpi/adaptiveproduct_youtube_music_foreground_color_108.png new file mode 100644 index 000000000..743b3944a Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-mdpi/adaptiveproduct_youtube_music_foreground_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-mdpi/ic_launcher_release.png b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-mdpi/ic_launcher_release.png new file mode 100644 index 000000000..98f3da557 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-mdpi/ic_launcher_release.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xhdpi/adaptiveproduct_youtube_music_background_color_108.png b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xhdpi/adaptiveproduct_youtube_music_background_color_108.png new file mode 100644 index 000000000..a95aff113 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xhdpi/adaptiveproduct_youtube_music_background_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xhdpi/adaptiveproduct_youtube_music_foreground_color_108.png b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xhdpi/adaptiveproduct_youtube_music_foreground_color_108.png new file mode 100644 index 000000000..684757788 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xhdpi/adaptiveproduct_youtube_music_foreground_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xhdpi/ic_launcher_release.png b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xhdpi/ic_launcher_release.png new file mode 100644 index 000000000..f4f9d8f9e Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xhdpi/ic_launcher_release.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_music_background_color_108.png b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_music_background_color_108.png new file mode 100644 index 000000000..d6cec4cce Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_music_background_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_music_foreground_color_108.png b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_music_foreground_color_108.png new file mode 100644 index 000000000..ca5978b3d Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_music_foreground_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xxhdpi/ic_launcher_release.png b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xxhdpi/ic_launcher_release.png new file mode 100644 index 000000000..361fe7224 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xxhdpi/ic_launcher_release.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_music_background_color_108.png b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_music_background_color_108.png new file mode 100644 index 000000000..6ef5ac482 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_music_background_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_music_foreground_color_108.png b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_music_foreground_color_108.png new file mode 100644 index 000000000..e65f37ae1 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_music_foreground_color_108.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/ic_launcher_release.png b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/ic_launcher_release.png new file mode 100644 index 000000000..a435915f5 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/ic_launcher_release.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/monochrome/drawable/ic_app_icons_themed_youtube_music.xml b/src/main/resources/music/branding/mmt_turquoise/monochrome/drawable/ic_app_icons_themed_youtube_music.xml new file mode 100644 index 000000000..e1fdba50d --- /dev/null +++ b/src/main/resources/music/branding/mmt_turquoise/monochrome/drawable/ic_app_icons_themed_youtube_music.xml @@ -0,0 +1,13 @@ + + + diff --git a/src/main/resources/music/branding/mmt_turquoise/settings/drawable/revanced_extended_settings_key_icon.xml b/src/main/resources/music/branding/mmt_turquoise/settings/drawable/revanced_extended_settings_key_icon.xml new file mode 100755 index 000000000..473bd9c8b --- /dev/null +++ b/src/main/resources/music/branding/mmt_turquoise/settings/drawable/revanced_extended_settings_key_icon.xml @@ -0,0 +1,1038 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/music/branding/mmt_turquoise/splash/drawable-hdpi/action_bar_logo_release.png b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-hdpi/action_bar_logo_release.png new file mode 100644 index 000000000..522e9763b Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-hdpi/action_bar_logo_release.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/splash/drawable-hdpi/record.png b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-hdpi/record.png new file mode 100644 index 000000000..c459f1c5f Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-hdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/splash/drawable-large-hdpi/record.png b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-large-hdpi/record.png new file mode 100644 index 000000000..920b49c06 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-large-hdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/splash/drawable-large-mdpi/record.png b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-large-mdpi/record.png new file mode 100644 index 000000000..7076ceee6 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-large-mdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/splash/drawable-large-xhdpi/record.png b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-large-xhdpi/record.png new file mode 100644 index 000000000..92a28562c Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-large-xhdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/splash/drawable-mdpi/record.png b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-mdpi/record.png new file mode 100644 index 000000000..3cb25655f Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-mdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/splash/drawable-xhdpi/record.png b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-xhdpi/record.png new file mode 100644 index 000000000..833f1a0b4 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-xhdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/splash/drawable-xlarge-hdpi/record.png b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-xlarge-hdpi/record.png new file mode 100644 index 000000000..1ec1319a4 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-xlarge-hdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/splash/drawable-xlarge-mdpi/record.png b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-xlarge-mdpi/record.png new file mode 100644 index 000000000..833f1a0b4 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-xlarge-mdpi/record.png differ diff --git a/src/main/resources/music/branding/mmt_turquoise/splash/drawable-xxhdpi/record.png b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-xxhdpi/record.png new file mode 100644 index 000000000..1ec1319a4 Binary files /dev/null and b/src/main/resources/music/branding/mmt_turquoise/splash/drawable-xxhdpi/record.png differ diff --git a/src/main/resources/music/settings/host/values/strings.xml b/src/main/resources/music/settings/host/values/strings.xml index b329e98e4..975e7684e 100644 --- a/src/main/resources/music/settings/host/values/strings.xml +++ b/src/main/resources/music/settings/host/values/strings.xml @@ -31,10 +31,12 @@ Tap on the continue button and disable battery optimizations." Enables the custom filter to hide layout components. Enable custom filter Invalid custom filter: %s. - Custom speeds must be less than %sx. Using default values. - Invalid custom playback speeds. Using default values. + Custom speeds must be less than %sx. + Invalid custom playback speeds. Add or change available playback speeds. Edit custom playback speeds + To open YouTube Music links in RVX Music, enable \'Open supported links\' and enable the supported web addresses. + Open default app settings Disables captions from being automatically enabled. Disable forced auto captions Disables Cairo splash animation when the app starts up. @@ -87,6 +89,7 @@ Info: Enable Zen mode in podcasts Changes the player background color to light grey to reduce eye strain. Enable Zen mode + Reset to default values. Restart to load the layout normally Refresh and restart Export settings to file @@ -317,7 +320,7 @@ Some features may not work properly in the old player layout." The address SponsorBlock uses to make calls to the server. Do not change this unless you know what you\'re doing. Color changed. Color: - Invalid color code. Color reset to default. + Invalid color code. Color reset. Change segment behavior Enable SponsorBlock diff --git a/src/main/resources/music/translations/bg-rBG/missing_strings.xml b/src/main/resources/music/translations/bg-rBG/missing_strings.xml index 4333d26db..b2b03a1e0 100644 --- a/src/main/resources/music/translations/bg-rBG/missing_strings.xml +++ b/src/main/resources/music/translations/bg-rBG/missing_strings.xml @@ -19,7 +19,9 @@ Tap on the continue button and disable battery optimizations." Bypass image region restrictions Change from in-app share sheet to system share sheet. Change share sheet - Invalid custom playback speeds. Using default values. + Invalid custom playback speeds. + To open YouTube Music links in RVX Music, enable \'Open supported links\' and enable the supported web addresses. + Open default app settings Disables Cairo splash animation when the app starts up. Disable Cairo splash animation Disable swipe to change tracks in the miniplayer. @@ -44,6 +46,7 @@ Info: Enable swipe to dismiss miniplayer Also enables Zen mode for podcasts. Enable Zen mode in podcasts + Reset to default values. Export settings to file Failed to export settings. Settings were successfully exported. @@ -125,7 +128,7 @@ Some features may not work properly in the old player layout." The address SponsorBlock uses to make calls to the server. Do not change this unless you know what you\'re doing. Color changed. Color: - Invalid color code. Color reset to default. + Invalid color code. Color reset. Change segment behavior Enable SponsorBlock diff --git a/src/main/resources/music/translations/bn/missing_strings.xml b/src/main/resources/music/translations/bn/missing_strings.xml index f7912b645..9d4d2191a 100644 --- a/src/main/resources/music/translations/bn/missing_strings.xml +++ b/src/main/resources/music/translations/bn/missing_strings.xml @@ -27,7 +27,9 @@ Tap on the continue button and disable battery optimizations." Select which page the app opens in. Change start page Invalid custom filter: %s. - Invalid custom playback speeds. Using default values. + Invalid custom playback speeds. + To open YouTube Music links in RVX Music, enable \'Open supported links\' and enable the supported web addresses. + Open default app settings Disables Cairo splash animation when the app starts up. Disable Cairo splash animation Disables redirection to the next track when clicking the Dislike button. @@ -59,6 +61,7 @@ Info: Add Trim silence switch Also enables Zen mode for podcasts. Enable Zen mode in podcasts + Reset to default values. Restart to load the layout normally Refresh and restart Export settings to file @@ -250,7 +253,7 @@ Some features may not work properly in the old player layout." The address SponsorBlock uses to make calls to the server. Do not change this unless you know what you\'re doing. Color changed. Color: - Invalid color code. Color reset to default. + Invalid color code. Color reset. Change segment behavior Enable SponsorBlock diff --git a/src/main/resources/music/translations/cs-rCZ/missing_strings.xml b/src/main/resources/music/translations/cs-rCZ/missing_strings.xml index 977ad6d6f..548b90a4f 100644 --- a/src/main/resources/music/translations/cs-rCZ/missing_strings.xml +++ b/src/main/resources/music/translations/cs-rCZ/missing_strings.xml @@ -28,10 +28,12 @@ Tap on the continue button and disable battery optimizations." Change start page List of component path builder strings to filter, separated by new lines. Invalid custom filter: %s. - Custom speeds must be less than %sx. Using default values. - Invalid custom playback speeds. Using default values. + Custom speeds must be less than %sx. + Invalid custom playback speeds. Add or change available playback speeds. Edit custom playback speeds + To open YouTube Music links in RVX Music, enable \'Open supported links\' and enable the supported web addresses. + Open default app settings Disables Cairo splash animation when the app starts up. Disable Cairo splash animation Disables redirection to the next track when clicking the Dislike button. @@ -63,6 +65,7 @@ Info: Add Trim silence switch Also enables Zen mode for podcasts. Enable Zen mode in podcasts + Reset to default values. Export settings to file Failed to export settings. Settings were successfully exported. @@ -274,7 +277,7 @@ Some features may not work properly in the old player layout." The address SponsorBlock uses to make calls to the server. Do not change this unless you know what you\'re doing. Color changed. Color: - Invalid color code. Color reset to default. + Invalid color code. Color reset. Change segment behavior Enable SponsorBlock diff --git a/src/main/resources/music/translations/el-rGR/strings.xml b/src/main/resources/music/translations/el-rGR/strings.xml index d683f2faa..820702ae3 100644 --- a/src/main/resources/music/translations/el-rGR/strings.xml +++ b/src/main/resources/music/translations/el-rGR/strings.xml @@ -16,7 +16,7 @@ Το MicroG GmsCore δεν είναι εγκατεστημένο. Εγκαταστήστε το. Αντικατάσταση του domain για την φόρτωση εικόνων όπου είναι μπλοκαρισμένες σε ορισμένες περιοχές ώστε να μπορούν να ληφθούν μικρογραφίες βίντεο, εικόνες δημοσιεύσεων, κλπ. Παράκαμψη μπλοκαρίσματος φόρτωσης εικόνων - Αλλαγή του μενού κοινοποίησης σε αυτό του συστήματος σας αντί του YouTube. + Αλλαγή του μενού κοινοποίησης σε αυτό του συστήματος σας αντί του YouTube Music. Αλλαγή μενού κοινοποίησης Διαγράμματα Εξερεύνηση @@ -30,10 +30,12 @@ Χρήση προσαρμοσμένου φίλτρου για απόκρυψη στοιχείων διεπαφής. Χρήση προσαρμοσμένου φίλτρου Μη έγκυρο φίλτρο: %s. - Οι ταχύτητες πρέπει να είναι μικρότερες από %sx, επαναφέρθηκαν. - Μη έγκυρες ταχύτητες αναπαραγωγής, επαναφέρθηκαν. + Οι ταχύτητες πρέπει να είναι μικρότερες από %sx. + Μη έγκυρες ταχύτητες αναπαραγωγής. Ρύθμιση των διαθέσιμων ταχυτήτων αναπαραγωγής. Επεξεργασία ταχυτήτων αναπαραγωγής + Για να ανοίγουν οι συνδέσμοι YouTube Music στο RVX Music, ενεργοποιήστε το «Άνοιγμα υποστηριζόμενων συνδέσμων» και τις υποστηριζόμενες διευθύνσεις ιστού. + Άνοιγμα ρυθμίσεων προεπιλεγμένων εφαρμογών Απενεργοποίηση της αυτόματης ενεργοποίησης υπότιτλων. Απενεργοποίηση αυτόματων υπότιτλων Απενεργοποίηση των εφέ θέματος Cairo κατά την εκκίνηση της εφαρμογής. @@ -84,6 +86,7 @@ Λειτουργία zen σε ηχητικές εκπομπές Προσθήκη μιας γκρι απόχρωσης στο παρασκήνιο της οθόνης αναπαραγωγής για να μειωθεί η καταπόνηση των ματιών. Ενεργοποίηση λειτουργίας zen + Επαναφέρθηκε στην προεπιλεγμένη τιμή. Επανεκκίνηση ώστε να φορτωθεί σωστά η εφαρμογή Ανανέωση και επανεκκίνηση Εξαγωγή ρυθμίσεων σε αρχείο @@ -314,7 +317,7 @@ Η διεύθυνση που χρησιμοποιείται για επικοινωνία με τον διακομιστή του SponsorBlock. Μη το αλλάξετε αν δεν ξέρετε τι κάνετε. Το χρώμα άλλαξε. Χρώμα: - Μη έγκυρος κωδικός χρώματος, επαναφέρθηκε. + Μη έγκυρος κωδικός χρώματος. Το χρώμα επαναφέρθηκε. Αλλαγή συμπεριφοράς τμημάτων Ενεργοποίηση του SponsorBlock diff --git a/src/main/resources/music/translations/es-rES/strings.xml b/src/main/resources/music/translations/es-rES/strings.xml index a96ce7e94..5e17f78f0 100644 --- a/src/main/resources/music/translations/es-rES/strings.xml +++ b/src/main/resources/music/translations/es-rES/strings.xml @@ -34,6 +34,8 @@ Pulsa el botón de continuar y desactiva las optimizaciones de la batería."Velocidades de reproducción personalizadas no válidas. Utilizando valores predeterminados. Agregar o cambiar las velocidades de reproducción disponibles. Editar velocidades de reproducción personalizadas + Para abrir los enlaces de YouTube Music en RVX Music, activa \'Abrir enlaces soportados\' y activa las direcciones web soportadas. + Abrir ajustes predeterminados de la app Desactiva la activación automática de los subtítulos forzados en el reproductor de vídeo. Desactivar subtítulos automáticos Deshabilita la animación de bienvenida \"Cairo\" cuando se inicia la aplicación. @@ -82,6 +84,7 @@ Esta función aún está en desarrollo, por lo que puede ser inestable."Activar el modo Zen en podcasts Añade un tinte gris al reproductor de vídeo para reducir la fatiga visual. Activar modo zen + Restablecer a valores por defecto. Reiniciar para cargar el diseño normalmente Actualizar y reiniciar Exportar ajustes a archivo diff --git a/src/main/resources/music/translations/fr-rFR/strings.xml b/src/main/resources/music/translations/fr-rFR/strings.xml index 91ac54969..e490c29dd 100644 --- a/src/main/resources/music/translations/fr-rFR/strings.xml +++ b/src/main/resources/music/translations/fr-rFR/strings.xml @@ -30,10 +30,12 @@ Cliquez sur le bouton Continuer et désactivez les optimisations de la batterie. Active les filtres personnalisés pour masquer des éléments de l’interface. Activer le filtre personnalisé Filtre personnalisé invalide : %s. - Les vitesses personnalisées doivent être inférieures à %sx. Valeur réinitialisée par défaut. - Vitesses de lecture invalides. Valeur réinitialisée par défaut. + Les vitesses personnalisées doivent être inférieures à %sx. + Vitesses de lecture invalides. Ajoute ou modifie les vitesses de lecture disponibles. Éditez les vitesses de lecture personnalisées + Pour ouvrir les liens YouTube Music dans RVX Music, activez \'Ouvrir les liens compatibles\' et activez les adresses web prises en charge. + Ouvrir les paramètres par défaut de l\'application Désactive les sous-titres automatiquement activés. Désactiver les sous-titres forcés Désactive l\'animation Cairo lors du démarrage de l\'application. @@ -86,6 +88,7 @@ Info : Activer le mode \"Zen\" sur les Podcasts Change la couleur du lecteur par un voile gris pour réduire la fatigue oculaire. Activer le mode zen + Réinitialiser les valeurs par défaut. Redémarrer pour charger l\'interface correctement Appliquer et redémarrer ? Exporter les paramètres vers un fichier @@ -316,7 +319,7 @@ Certaines fonctions peuvent ne pas fonctionner sur l'ancienne mise en page."L\'adresse qu\'utilise SponsorBlock pour contacter le serveur. Ne le modifiez que si vous savez ce que vous faites. Couleur modifiée. Couleur (hex) : - Code couleur invalide. Couleur réinitialisée par défaut. + Code couleur invalide. Couleur réinitialisée. Modifier le comportement des segments Activer Sponsorblock diff --git a/src/main/resources/music/translations/hu-rHU/missing_strings.xml b/src/main/resources/music/translations/hu-rHU/missing_strings.xml index 73bfca33a..ff3a986a9 100644 --- a/src/main/resources/music/translations/hu-rHU/missing_strings.xml +++ b/src/main/resources/music/translations/hu-rHU/missing_strings.xml @@ -1,12 +1,13 @@ Don\'t show again + To open YouTube Music links in RVX Music, enable \'Open supported links\' and enable the supported web addresses. + Open default app settings Disables Cairo splash animation when the app starts up. Disable Cairo splash animation + Reset to default values. Displays the optimization dialog for GMSCore at each application startup. Show optimization dialog for GMSCore - Hides the promotion alert banner. - Hide promotion alert banner Show a toast when changing the default playback speed. Show a toast Show a toast when changing the default video quality. diff --git a/src/main/resources/music/translations/hu-rHU/strings.xml b/src/main/resources/music/translations/hu-rHU/strings.xml index 6f0ecdea7..2230fb505 100644 --- a/src/main/resources/music/translations/hu-rHU/strings.xml +++ b/src/main/resources/music/translations/hu-rHU/strings.xml @@ -221,6 +221,8 @@ Ha tiltva van, akkor blokkolja a t. k. hírdetéseket. (lehetnek mellékhatások Felugró prémium hírdetések elrejtése Elrejti a prémium megújítás szalaghírdetést. Prémium megújítás szalaghírdetés elrejtése + Promóciós figyelmeztető banner elrejtése. + Promóciós figyelmeztető banner elrejtése Elrejti a minták polcot a főoldalon. Minták polc elrejtése A beállítások menüben szűrendő nevek listája, új sorokkal elválasztva. diff --git a/src/main/resources/music/translations/id-rID/missing_strings.xml b/src/main/resources/music/translations/id-rID/missing_strings.xml index 34e49809f..4f34cdc34 100644 --- a/src/main/resources/music/translations/id-rID/missing_strings.xml +++ b/src/main/resources/music/translations/id-rID/missing_strings.xml @@ -1,8 +1,11 @@ Don\'t show again + To open YouTube Music links in RVX Music, enable \'Open supported links\' and enable the supported web addresses. + Open default app settings Disables Cairo splash animation when the app starts up. Disable Cairo splash animation + Reset to default values. Displays the optimization dialog for GMSCore at each application startup. Show optimization dialog for GMSCore Hides the promotion alert banner. diff --git a/src/main/resources/music/translations/in/missing_strings.xml b/src/main/resources/music/translations/in/missing_strings.xml index 34e49809f..4f34cdc34 100644 --- a/src/main/resources/music/translations/in/missing_strings.xml +++ b/src/main/resources/music/translations/in/missing_strings.xml @@ -1,8 +1,11 @@ Don\'t show again + To open YouTube Music links in RVX Music, enable \'Open supported links\' and enable the supported web addresses. + Open default app settings Disables Cairo splash animation when the app starts up. Disable Cairo splash animation + Reset to default values. Displays the optimization dialog for GMSCore at each application startup. Show optimization dialog for GMSCore Hides the promotion alert banner. diff --git a/src/main/resources/music/translations/it-rIT/missing_strings.xml b/src/main/resources/music/translations/it-rIT/missing_strings.xml index 4e4c9e290..0d71a39dc 100644 --- a/src/main/resources/music/translations/it-rIT/missing_strings.xml +++ b/src/main/resources/music/translations/it-rIT/missing_strings.xml @@ -27,7 +27,9 @@ Tap on the continue button and disable battery optimizations." Select which page the app opens in. Change start page Invalid custom filter: %s. - Invalid custom playback speeds. Using default values. + Invalid custom playback speeds. + To open YouTube Music links in RVX Music, enable \'Open supported links\' and enable the supported web addresses. + Open default app settings Disables Cairo splash animation when the app starts up. Disable Cairo splash animation Disables redirection to the next track when clicking the Dislike button. @@ -59,6 +61,7 @@ Info: Add Trim silence switch Also enables Zen mode for podcasts. Enable Zen mode in podcasts + Reset to default values. Restart to load the layout normally Refresh and restart Export settings to file @@ -255,7 +258,7 @@ Some features may not work properly in the old player layout." The address SponsorBlock uses to make calls to the server. Do not change this unless you know what you\'re doing. Color changed. Color: - Invalid color code. Color reset to default. + Invalid color code. Color reset. Change segment behavior Enable SponsorBlock diff --git a/src/main/resources/music/translations/ja-rJP/missing_strings.xml b/src/main/resources/music/translations/ja-rJP/missing_strings.xml new file mode 100644 index 000000000..f22480d7e --- /dev/null +++ b/src/main/resources/music/translations/ja-rJP/missing_strings.xml @@ -0,0 +1,6 @@ + + + To open YouTube Music links in RVX Music, enable \'Open supported links\' and enable the supported web addresses. + Open default app settings + Reset to default values. + diff --git a/src/main/resources/music/translations/ko-rKR/strings.xml b/src/main/resources/music/translations/ko-rKR/strings.xml index 0e33f01e3..789fb01e4 100644 --- a/src/main/resources/music/translations/ko-rKR/strings.xml +++ b/src/main/resources/music/translations/ko-rKR/strings.xml @@ -16,7 +16,7 @@ GmsCore 열기 GmsCore가 설치되어 있지 않습니다. 설치하세요. 이미지 도메인을 변경하여 일부 국가에서 차단된 재생목록 썸네일, 채널 프로필 사진, 커뮤니티 게시물 이미지 등을 수신할 수 있습니다. - 이미지 표시 제한 국가 우회하기 + 이미지 표시 제한 국가 우회 YT Music 기본 공유 시트에서 Android 기본 공유 시트로 변경합니다.\n\n• 공유 버튼으로 바로 Android 기본 공유 메뉴를 실행할 수 있습니다. 공유 시트 변경 차트 @@ -31,10 +31,12 @@ 사용자 정의 필터를 활성화하여 레이아웃 구성요소를 숨깁니다. 사용자 정의 필터 활성화 잘못된 필터 값입니다: %s - 사용자 정의 재생 속도는 %s배속보다 작아야 하므로 기본값으로 초기화합니다. - 잘못된 재생 속도 값이므로 기본값으로 초기화합니다. + 사용자 정의 재생 속도는 %s배속보다 작아야 합니다. + 잘못된 재생 속도 값입니다. 사용하고 싶은 재생 속도 값을 추가하거나 변경할 수 있습니다. 사용자 정의 재생 속도 편집 + YT Music 링크를 RVX Music으로 열려면 \'지원되는 링크 열기\'를 활성화하고 지원되는 링크를 추가하세요. 링크 추가가 잠겨있다면 순정 YT Music 앱 정보 → \'기본적으로 열기\'에서 \'지원되는 링크 열기\'를 비활성화한 후에 추가할 수 있습니다. + 기본 앱 설정 열기 자막 사용이 강제된 동영상에서 자막을 비활성화합니다. 자동 자막 비활성화 앱을 시작할 때, Cairo 스플래시 애니메이션을 비활성화합니다. @@ -87,6 +89,7 @@ 팟캐스트에서 집중 모드 활성화 동영상 플레이어의 색상을 회색조로 설정해 눈의 피로를 줄입니다. 집중 모드 활성화 + 기본값으로 초기화합니다. 레이아웃을 정상적으로 불러오기 위해 다시 시작합니다. 새로고침 및 다시 시작 파일로 설정 내보내기 @@ -257,7 +260,7 @@ YT Music 설정 메뉴뿐만 아니라 ReVanced Extended 설정 메뉴도 숨겨 재생 속도 값을 변경할 때마다 저장합니다. 재생 속도 저장 활성화 기본 동영상 재생 속도 값으로 변경되었을 때, 팝업 메시지를 표시합니다. - 팝업 메시지 표시하기 + 팝업 메시지 표시 기본 재생 속도 값을 %s으로 변경합니다. 반복 재생 토글 상태를 저장합니다. 반복 상태 저장 @@ -266,7 +269,7 @@ YT Music 설정 메뉴뿐만 아니라 ReVanced Extended 설정 메뉴도 숨겨 동영상 품질 값을 변경할 때마다 저장합니다. 동영상 품질 저장 활성화 기본 동영상 화질 값으로 변경되었을 때, 팝업 메시지를 표시합니다. - 팝업 메시지 표시하기 + 팝업 메시지 표시 모바일 네트워크 이용 시 기본 동영상 품질 값을 %s로 변경합니다. 동영상 품질을 설정할 수 없습니다. Wi-Fi 이용 시 기본 동영상 품질 값을 %s로 변경합니다. @@ -320,7 +323,7 @@ YT Music 설정 메뉴뿐만 아니라 ReVanced Extended 설정 메뉴도 숨겨 SponsorBlock이 요청을 보낼 서버 URL입니다. 이것이 무슨 역할을 하는지 모르는 경우에는 이 URL을 변경하지 마세요. 설정한 색상을 적용하였습니다. 색상: - 잘못된 헥스 코드이므로 기본값으로 초기화합니다. + 잘못된 헥스 코드입니다. 색상을 초기화하였습니다. 각 구간에 설정할 동작 SponsorBlock 활성화 diff --git a/src/main/resources/music/translations/nl-rNL/missing_strings.xml b/src/main/resources/music/translations/nl-rNL/missing_strings.xml index fab175110..09a8e1b20 100644 --- a/src/main/resources/music/translations/nl-rNL/missing_strings.xml +++ b/src/main/resources/music/translations/nl-rNL/missing_strings.xml @@ -27,7 +27,9 @@ Tap on the continue button and disable battery optimizations." Select which page the app opens in. Change start page Invalid custom filter: %s. - Invalid custom playback speeds. Using default values. + Invalid custom playback speeds. + To open YouTube Music links in RVX Music, enable \'Open supported links\' and enable the supported web addresses. + Open default app settings Disables Cairo splash animation when the app starts up. Disable Cairo splash animation Disables redirection to the next track when clicking the Dislike button. @@ -40,6 +42,7 @@ Tap on the continue button and disable battery optimizations." Enable black player background Includes the buffer in the debug log. Enable debug buffer logging + Reset to default values. Reset Displays the optimization dialog for GMSCore at each application startup. Show optimization dialog for GMSCore @@ -134,7 +137,7 @@ Some features may not work properly in the old player layout." The address SponsorBlock uses to make calls to the server. Do not change this unless you know what you\'re doing. Color changed. Color: - Invalid color code. Color reset to default. + Invalid color code. Color reset. Change segment behavior Enable SponsorBlock diff --git a/src/main/resources/music/translations/pl-rPL/strings.xml b/src/main/resources/music/translations/pl-rPL/strings.xml index b1601c692..e3aa21676 100644 --- a/src/main/resources/music/translations/pl-rPL/strings.xml +++ b/src/main/resources/music/translations/pl-rPL/strings.xml @@ -30,10 +30,12 @@ Kontynuuj i wyłącz optymalizację baterii." Włącza własny filtr do ukrywania komponentów układu aplikacji. Włącz własny filtr Nieprawidłowy własny filtr: %s. - Nieprawidłowe niestandardowe prędkości odtwarzania. Przywrócono domyślne wartości. - Nieprawidłowe niestandardowe prędkości odtwarzania. Przywrócono domyślne wartości. + Niestandardowe prędkości muszą być mniejsze niż %sx. + Nieprawidłowe niestandardowe prędkości odtwarzania. Skonfiguruj dostępne prędkości odtwarzania. Edytuj niestandardowe prędkości odtwarzania + Aby otwierać linki YouTube Music w RVX Music, przejdź do opcji obsługiwanych linków w ustawieniach i włącz obsługiwane adresy internetowe dla RVX. + Otwórz systemowe ustawienia aplikacji Wyłącza automatycznie włączane napisy w odtwarzaczu filmów. Wyłącz automatyczne napisy Wyłącza animację ładowania aplikacji związaną z motywem Cairo podczas otwierania aplikacji. @@ -86,6 +88,7 @@ Informacje: Włącz tryb zen w podcastach Zmienia kolor tła odtwarzacza na jasnoszary, aby zmniejszyć zmęczenie oczu. Włącz tryb zen + Przywrócono domyślne wartości. Uruchom ponownie, aby wczytać układ poprawnie Odśwież i uruchom ponownie Wyeksportuj ustawienia do pliku @@ -316,7 +319,7 @@ Niektóre ustawienia mogą nie działać poprawnie ze starym układem odtwarzacz Adres SponsorBlock jest używany do wykonywania połączeń z serwerem. Nie zmieniaj tego, chyba że wiesz, co robisz. Kolor został zmieniony. Kolor: - Nieprawidłowy kod koloru. Przywrócono domyślny kolor. + Nieprawidłowy kod koloru. Kolor został zresetowany. Zmień sposoby pomijania segmentów Włącz SponsorBlock diff --git a/src/main/resources/music/translations/pt-rBR/strings.xml b/src/main/resources/music/translations/pt-rBR/strings.xml index e2f449289..3e03d003f 100644 --- a/src/main/resources/music/translations/pt-rBR/strings.xml +++ b/src/main/resources/music/translations/pt-rBR/strings.xml @@ -30,10 +30,12 @@ Toque no botão continuar e desative as otimizações da bateria." Ativa o filtro personalizado para ocultar componentes do layout. Ativar filtro personalizado Filtro personalizado inválido: %s. - Velocidades personalizadas devem ser menores que %sx. Usando valores padrão. - Velocidade personalizada de reprodução inválida. Usando valores padrão. + Velocidades personalizadas devem ser menores que %sx. + Velocidades de reprodução personalizadas inválidas. Adicionar ou alterar as velocidades de reprodução disponíveis. Editar velocidades de reprodução personalizadas + Para abrir os links de música do YouTube no RVX Music, ative \'Abrir links suportados\' e ative os endereços web suportados. + Abrir configurações padrão do aplicativo Desativa as legendas de serem ativadas automaticamente. Desativar legendas automáticas Desabilita a animação inicial do Cairo quando o aplicativo é iniciado. @@ -86,6 +88,7 @@ Informações: Ativar o modo Calmo em podcasts Altera a cor de fundo do reprodutor para cinza claro para reduzir o cansaço visual. Ativar modo Calmo + Redefinir para os valores padrão. Reinicie para carregar o layout normalmente Atualizar e reiniciar Exportar configurações para um arquivo @@ -316,7 +319,7 @@ Alguns recursos podem não funcionar corretamente no layout antigo do reprodutor O endereço que o SponsorBlock usa para fazer chamadas para o servidor. Não mude isso a menos que você saiba o que está fazendo. Cor alterada. Cor: - Código de cor inválido. Redefinir cor para o padrão. + Código de cor inválido. Redefinir cor. Alterar comportamento do segmento Ativar SponsorBlock diff --git a/src/main/resources/music/translations/ro-rRO/missing_strings.xml b/src/main/resources/music/translations/ro-rRO/missing_strings.xml index d515efc1f..76cfad333 100644 --- a/src/main/resources/music/translations/ro-rRO/missing_strings.xml +++ b/src/main/resources/music/translations/ro-rRO/missing_strings.xml @@ -27,7 +27,9 @@ Tap on the continue button and disable battery optimizations." Select which page the app opens in. Change start page Invalid custom filter: %s. - Invalid custom playback speeds. Using default values. + Invalid custom playback speeds. + To open YouTube Music links in RVX Music, enable \'Open supported links\' and enable the supported web addresses. + Open default app settings Disables Cairo splash animation when the app starts up. Disable Cairo splash animation Disables redirection to the next track when clicking the Dislike button. @@ -54,6 +56,7 @@ Info: Add Trim silence switch Also enables Zen mode for podcasts. Enable Zen mode in podcasts + Reset to default values. Restart to load the layout normally Refresh and restart Export settings to file @@ -240,7 +243,7 @@ Some features may not work properly in the old player layout." The address SponsorBlock uses to make calls to the server. Do not change this unless you know what you\'re doing. Color changed. Color: - Invalid color code. Color reset to default. + Invalid color code. Color reset. Change segment behavior Enable SponsorBlock diff --git a/src/main/resources/music/translations/ru-rRU/missing_strings.xml b/src/main/resources/music/translations/ru-rRU/missing_strings.xml index acebd7abf..c5ad0c8d9 100644 --- a/src/main/resources/music/translations/ru-rRU/missing_strings.xml +++ b/src/main/resources/music/translations/ru-rRU/missing_strings.xml @@ -1,6 +1,9 @@ Don\'t show again + To open YouTube Music links in RVX Music, enable \'Open supported links\' and enable the supported web addresses. + Open default app settings + Reset to default values. Displays the optimization dialog for GMSCore at each application startup. Show optimization dialog for GMSCore diff --git a/src/main/resources/music/translations/ru-rRU/strings.xml b/src/main/resources/music/translations/ru-rRU/strings.xml index da006db05..4d9fe34fa 100644 --- a/src/main/resources/music/translations/ru-rRU/strings.xml +++ b/src/main/resources/music/translations/ru-rRU/strings.xml @@ -16,8 +16,8 @@ GmsCore не установлен. Установите его. Заменяет заблокированный в некоторых регионах домен, чтобы можно было получать миниатюры плейлистов, аватары каналов и т. д. Обойти ограничения изображений по региону - Меняет встроенное диалоговое окно \"Поделиться\" на системное. - Изменить список \"Поделиться\" + Меняет тип диалогового окна \"Поделиться\" из встроенного на системное. + Изменить окно \"Поделиться\" Хит-парады Навигатор Главная diff --git a/src/main/resources/music/translations/tr-rTR/missing_strings.xml b/src/main/resources/music/translations/tr-rTR/missing_strings.xml index b778a884c..341b53c4e 100644 --- a/src/main/resources/music/translations/tr-rTR/missing_strings.xml +++ b/src/main/resources/music/translations/tr-rTR/missing_strings.xml @@ -3,8 +3,11 @@ Don\'t show again Change from in-app share sheet to system share sheet. Change share sheet + To open YouTube Music links in RVX Music, enable \'Open supported links\' and enable the supported web addresses. + Open default app settings Disables Cairo splash animation when the app starts up. Disable Cairo splash animation + Reset to default values. Displays the optimization dialog for GMSCore at each application startup. Show optimization dialog for GMSCore Hides the promotion alert banner. diff --git a/src/main/resources/music/translations/uk-rUA/strings.xml b/src/main/resources/music/translations/uk-rUA/strings.xml index 4dedd6855..9a5eb470a 100644 --- a/src/main/resources/music/translations/uk-rUA/strings.xml +++ b/src/main/resources/music/translations/uk-rUA/strings.xml @@ -16,7 +16,7 @@ GmsCore не встановлено. Встановіть. Замінює домен для зображень, заблокований у деяких регіонах, що дозволить отримувати мініатюри списків відтворення, аватари каналів тощо. Змінити домен зображень - Змінює тип вікна діалогу поширення з вбудованого до системного. + Змінює тип вікна діалогу поширення з вбудованого на системний. Змінити діалог поширення Хіт-паради Навігація @@ -30,10 +30,12 @@ Вмикає користувацькі фільтри для приховування компонентів інтерфейсу. Увімкнути користувацький фільтр Недопустимий користувацький фільтр: %s. - Користувацькі швидкості мають бути меншими за %sx. Швидкості скинуто до стандартних значень. - Неправильні користувацькі швидкості відтворення. Використовуються типові значення. + Користувацькі швидкості мають бути меншими за %sx. + Неправильні користувацькі швидкості відтворення. Налаштувати доступні швидкості відтворення. Редагувати користувацькі швидкості відтворення + Щоб відкривати посилання на YouTube Music у RVX Music, увімкніть \"Відкривати підтримувані посилання\" та активуйте підтримувані веб-адреси. + Відкрити налаштування за замовчуванням Вимикає автоматичне ввімкнення субтитрів. Вимкнути примусові авто субтитри Вимикає сплеш анімацію Каїр під час запуску застосунку. @@ -86,6 +88,7 @@ Увімкнути режим \"Дзен\" у подкастах Змінює колір фона плеєра на світло-сірий, щоб зменшити навантаження на очі. Увімкнути режим \"Дзен\" + Скинуто до значень за замовчуванням. Перезапустіть, щоб нормально завантажився макет Оновити та перезавантажити? Експорт налаштувань у файл @@ -316,7 +319,7 @@ Адреса, яку SponsorBlock використовує для звернень до сервера. Не змінюйте це, якщо не знаєте, що робите. Колір змінено. Колір: - Недійсний код кольору. Колір скинуто до стандартного. + Недійсний код кольору. Колір скинуто. Змінити поведінку сегмента Увімкнути SponsorBlock diff --git a/src/main/resources/music/translations/vi-rVN/strings.xml b/src/main/resources/music/translations/vi-rVN/strings.xml index b7519c842..6a8e18329 100644 --- a/src/main/resources/music/translations/vi-rVN/strings.xml +++ b/src/main/resources/music/translations/vi-rVN/strings.xml @@ -28,10 +28,12 @@ Làm theo hướng dẫn 'Don't kill my app!' cho thiết bị của bạn và Ẩn các thành phần không mong muốn bằng bộ lọc tuỳ chỉnh. Bộ lọc tuỳ chỉnh Bộ lọc tuỳ chỉnh không hợp lệ: %s. - Tốc độ phát tuỳ chỉnh không hợp lệ. Đã đặt lại tốc độ phát về mặc định. - Tốc độ phát tùy chỉnh không hợp lệ. Đã khôi phục lại các giá trị mặc định. + Tốc độ phát tuỳ chỉnh phải nhỏ hơn %sx. + Tốc độ phát tùy chỉnh không hợp lệ. Thêm giá trị tốc độ phát mà bạn muốn thay đổi hoặc chỉnh sửa các giá trị tốc độ phát hiện có. Chỉnh sửa tốc độ phát + Để mở liên kết YouTube Music trong RVX Music, hãy bật \'Mở liên kết được hỗ trợ\' và kích hoạt các địa chỉ web được hỗ trợ. + Mở theo mặc định Tắt tự động hiển thị phụ đề khi phát video nhạc có phụ đề. Tắt tự động hiển thị phụ đề Vô hiệu hóa hoạt ảnh Cairo khi ứng dụng khởi chạy. @@ -66,20 +68,25 @@ Hạn chế: Thêm nút tiếp theo vào trình phát thu nhỏ Thêm nút bài hát trước đó vào trình phát thu nhỏ. Thêm nút phát trước đó vào trình phát thu nhỏ - "Áp dụng codec âm thanh Opus thay vì MP4A." - Codec Opus + "Áp dụng bộ giải mã OPUS nếu phản hồi của trình phát bao gồm nó. + +Cụ thể: +• Ứng dụng YouTube Music mới nhất đặt mặc định là bộ giải mãi OPUS. +• Điều này chỉ áp dụng cho người dùng giả mạo với các phiên bản ứng dụng rất cũ." + Bộ giải mã OPUS Bật thao tác vuốt xuống để loại bỏ trình phát thu nhỏ. Bật thao tác vuốt để loại bỏ trình phát thu nhỏ - "Thêm nút Bật/Tắt Cắt bỏ khoảng im lặng vào tuỳ chọn tốc độ phát. + "Thêm tính năng Cắt bỏ khoảng lặng vào mục tuỳ chọn tốc độ phát. Cụ thể: - • Tính năng dành cho podcast. - • Tính năng vẫn đang được phát triển nên có thể chưa ổn định." - Bật/Tắt Cắt bỏ khoảng im lặng + • Tính năng này dành cho podcast. + • Tính năng này vẫn đang được phát triển nên có thể chưa ổn định." + Cắt bỏ khoảng lặng Đồng thời bật chế độ tập trung cho podcast. Bật Chế độ tập trung trong podcasts Thay đổi nền của trình phát thành màu xám nhạt để giúp bạn giảm mỏi mắt và tập trung hơn. Chế độ tập trung + Đặt lại về giá trị mặc định. Vui lòng khởi động lại ứng dụng để các tính năng hoạt động bình thường Làm mới và khởi động lại Xuất cài đặt dưới dạng tệp @@ -222,14 +229,14 @@ Nếu tính năng này tắt, quảng cáo toàn màn hình sẽ bị chặn (c Ẩn thẻ Đoạn nhạc trong bảng feed. Ẩn thẻ Đoạn nhạc Danh sách tên menu Cài đặt cần lọc, cách nhau từng dòng một. - Cài đặt bộ lọc menu - "Ẩn các thành phần của menu Cài đặt. -Khi bật không chỉ ẩn menu Cài đặt YT Music, mà cả menu Cài đặt ReVanced Extended." - Ẩn menu cài đặt + Cài đặt bộ lọc + "Ẩn các thành phần của mục Cài đặt. +Khi bật không những ẩn mục Cài đặt YT Music, mà còn ẩn mục Cài đặt ReVanced Extended." + Ẩn mục cài đặt Ẩn nút tìm kiếm âm thanh trên thanh tìm kiếm. Ẩn nút tìm kiếm âm thanh Ẩn nút \'Chạm để nâng cấp\'. - Ẩn nút \'Chạm để nâng cấp\' + Ẩn nút Nhấn để cập nhật Ẩn các mục Chính sách quyền riêng tư và Điều khoản dịch vụ khỏi trình đơn Tài khoản. Ẩn mục Bảo mật và Điều khoản Ẩn nút tìm kiếm bằng giọng nói trên thanh tìm kiếm. @@ -310,7 +317,7 @@ Khi bật không chỉ ẩn menu Cài đặt YT Music, mà cả menu Cài đặt Địa chỉ Url của Api SponsorBlock được dùng để thực hiện các kết nối đến máy chủ. Không thay đổi địa chỉ này trừ khi bạn biết mình đang làm gì. Đã thay đổi màu phân đoạn. Màu: - Mã màu không hợp lệ. Đã đặt lại màu về mặc định. + Mã màu không hợp lệ. Đã đặt lại màu phân đoạn về mặc định. Thay đổi hành vi của phân đoạn Kích hoạt SponsorBlock diff --git a/src/main/resources/music/translations/zh-rCN/missing_strings.xml b/src/main/resources/music/translations/zh-rCN/missing_strings.xml index 7c2f73738..d285408c1 100644 --- a/src/main/resources/music/translations/zh-rCN/missing_strings.xml +++ b/src/main/resources/music/translations/zh-rCN/missing_strings.xml @@ -19,7 +19,9 @@ Tap on the continue button and disable battery optimizations." Bypass image region restrictions Change from in-app share sheet to system share sheet. Change share sheet - Invalid custom playback speeds. Using default values. + Invalid custom playback speeds. + To open YouTube Music links in RVX Music, enable \'Open supported links\' and enable the supported web addresses. + Open default app settings Disables Cairo splash animation when the app starts up. Disable Cairo splash animation Disable swipe to change tracks in the miniplayer. @@ -28,6 +30,7 @@ Tap on the continue button and disable battery optimizations." Disable player gesture Includes the buffer in the debug log. Enable debug buffer logging + Reset to default values. Reset Displays the optimization dialog for GMSCore at each application startup. Show optimization dialog for GMSCore @@ -74,7 +77,7 @@ Some features may not work properly in the old player layout." The address SponsorBlock uses to make calls to the server. Do not change this unless you know what you\'re doing. Color changed. Color: - Invalid color code. Color reset to default. + Invalid color code. Color reset. Change segment behavior Enable SponsorBlock diff --git a/src/main/resources/music/translations/zh-rTW/missing_strings.xml b/src/main/resources/music/translations/zh-rTW/missing_strings.xml index 71dc3df5b..5a5fb5e0b 100644 --- a/src/main/resources/music/translations/zh-rTW/missing_strings.xml +++ b/src/main/resources/music/translations/zh-rTW/missing_strings.xml @@ -19,6 +19,8 @@ Tap on the continue button and disable battery optimizations." Bypass image region restrictions Change from in-app share sheet to system share sheet. Change share sheet + To open YouTube Music links in RVX Music, enable \'Open supported links\' and enable the supported web addresses. + Open default app settings Disables Cairo splash animation when the app starts up. Disable Cairo splash animation Disable swipe to change tracks in the miniplayer. @@ -27,6 +29,7 @@ Tap on the continue button and disable battery optimizations." Disable player gesture Includes the buffer in the debug log. Enable debug buffer logging + Reset to default values. Reset Displays the optimization dialog for GMSCore at each application startup. Show optimization dialog for GMSCore @@ -54,7 +57,7 @@ This hides not only the YT Music settings menu, but also the ReVanced Extended s Data is provided by the SponsorBlock API. Tap here to learn more and see downloads for other platforms. Color changed. Color: - Invalid color code. Color reset to default. + Invalid color code. Color reset. Reset color Skip automatically diff --git a/src/main/resources/youtube/branding/afn_blue/settings/drawable/revanced_extended_settings_key_icon.xml b/src/main/resources/youtube/branding/afn_blue/settings/drawable/revanced_extended_settings_key_icon.xml index ede82d9f1..c420684c3 100644 --- a/src/main/resources/youtube/branding/afn_blue/settings/drawable/revanced_extended_settings_key_icon.xml +++ b/src/main/resources/youtube/branding/afn_blue/settings/drawable/revanced_extended_settings_key_icon.xml @@ -1,2032 +1,29 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:height="48dp" + android:viewportWidth="740" + android:viewportHeight="740"> + + + + diff --git a/src/main/resources/youtube/branding/afn_blue/splash/drawable/avd_anim.xml b/src/main/resources/youtube/branding/afn_blue/splash/drawable/avd_anim.xml index c9061c82a..951215995 100644 --- a/src/main/resources/youtube/branding/afn_blue/splash/drawable/avd_anim.xml +++ b/src/main/resources/youtube/branding/afn_blue/splash/drawable/avd_anim.xml @@ -1,5 +1,96 @@ - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/youtube/branding/afn_red/settings/drawable/revanced_extended_settings_key_icon.xml b/src/main/resources/youtube/branding/afn_red/settings/drawable/revanced_extended_settings_key_icon.xml index bc9942311..97c066bd8 100644 --- a/src/main/resources/youtube/branding/afn_red/settings/drawable/revanced_extended_settings_key_icon.xml +++ b/src/main/resources/youtube/branding/afn_red/settings/drawable/revanced_extended_settings_key_icon.xml @@ -1,2232 +1,29 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:height="48dp" + android:viewportWidth="740" + android:viewportHeight="740"> + + + + diff --git a/src/main/resources/youtube/branding/afn_red/splash/drawable/avd_anim.xml b/src/main/resources/youtube/branding/afn_red/splash/drawable/avd_anim.xml index c9061c82a..877e9452b 100644 --- a/src/main/resources/youtube/branding/afn_red/splash/drawable/avd_anim.xml +++ b/src/main/resources/youtube/branding/afn_red/splash/drawable/avd_anim.xml @@ -1,5 +1,96 @@ - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/youtube/branding/mmt/settings/drawable/revanced_extended_settings_key_icon.xml b/src/main/resources/youtube/branding/mmt/settings/drawable/revanced_extended_settings_key_icon.xml index 085d98c17..13a1298ec 100644 --- a/src/main/resources/youtube/branding/mmt/settings/drawable/revanced_extended_settings_key_icon.xml +++ b/src/main/resources/youtube/branding/mmt/settings/drawable/revanced_extended_settings_key_icon.xml @@ -1,3288 +1,25 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + android:height="48dp" + android:viewportWidth="326" + android:viewportHeight="326"> + + + + diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-hdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-hdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..a8867dce6 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-hdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-hdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-hdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..2e20c3213 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-hdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-hdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-hdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..62d5f8403 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-hdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-hdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-hdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..af317f314 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-hdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-mdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-mdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..a6af8bd48 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-mdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-mdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-mdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..a767d9058 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-mdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-mdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-mdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..5315f5d0d Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-mdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-mdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-mdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..874c9e996 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-mdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-xhdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xhdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..68d838e86 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xhdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-xhdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xhdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..eb4584629 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xhdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-xhdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xhdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..841821ed5 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xhdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-xhdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xhdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..0be007c78 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xhdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxhdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxhdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..6b104026e Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxhdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxhdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxhdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..e6b6ff22f Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxhdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxhdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxhdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..5272b6207 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxhdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxhdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxhdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..3eed6df3c Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxhdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxxhdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxxhdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..1bc15a4e4 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxxhdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxxhdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxxhdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..ad5a31bf3 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxxhdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxxhdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxxhdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..aab80dcf6 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxxhdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxxhdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxxhdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..c5106a343 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/header/drawable-xxxhdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-hdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-hdpi/adaptiveproduct_youtube_background_color_108.png new file mode 100644 index 000000000..42a6d56e5 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-hdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-hdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-hdpi/adaptiveproduct_youtube_foreground_color_108.png new file mode 100644 index 000000000..61553bfd1 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-hdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-hdpi/ic_launcher.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..f8d1d9e78 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-hdpi/ic_launcher.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-hdpi/ic_launcher_round.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 000000000..f8d1d9e78 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-hdpi/ic_launcher_round.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-mdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-mdpi/adaptiveproduct_youtube_background_color_108.png new file mode 100644 index 000000000..51f2f5bcc Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-mdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-mdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-mdpi/adaptiveproduct_youtube_foreground_color_108.png new file mode 100644 index 000000000..b1de5860b Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-mdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-mdpi/ic_launcher.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..1464d4906 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-mdpi/ic_launcher.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-mdpi/ic_launcher_round.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 000000000..1464d4906 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-mdpi/ic_launcher_round.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xhdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xhdpi/adaptiveproduct_youtube_background_color_108.png new file mode 100644 index 000000000..caa231027 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xhdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xhdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xhdpi/adaptiveproduct_youtube_foreground_color_108.png new file mode 100644 index 000000000..857868a9b Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xhdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xhdpi/ic_launcher.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..304504f96 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xhdpi/ic_launcher.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xhdpi/ic_launcher_round.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 000000000..304504f96 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_background_color_108.png new file mode 100644 index 000000000..c6edf6ec9 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_foreground_color_108.png new file mode 100644 index 000000000..6eb4b0fff Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxhdpi/ic_launcher.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..6a247917a Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxhdpi/ic_launcher_round.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..6a247917a Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_background_color_108.png new file mode 100644 index 000000000..0f70382df Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_foreground_color_108.png new file mode 100644 index 000000000..a80df8729 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxxhdpi/ic_launcher.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..5d2fa41fc Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxxhdpi/ic_launcher_round.png b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..5d2fa41fc Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/launcher/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/monochrome/drawable/adaptive_monochrome_ic_youtube_launcher.xml b/src/main/resources/youtube/branding/mmt_orange/monochrome/drawable/adaptive_monochrome_ic_youtube_launcher.xml new file mode 100644 index 000000000..aec9f0686 --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_orange/monochrome/drawable/adaptive_monochrome_ic_youtube_launcher.xml @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/src/main/resources/youtube/branding/mmt_orange/settings/drawable/revanced_extended_settings_key_icon.xml b/src/main/resources/youtube/branding/mmt_orange/settings/drawable/revanced_extended_settings_key_icon.xml new file mode 100755 index 000000000..7702377fc --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_orange/settings/drawable/revanced_extended_settings_key_icon.xml @@ -0,0 +1,954 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-hdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-hdpi/product_logo_youtube_color_144.png new file mode 100644 index 000000000..22337c0fa Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-hdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-hdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-hdpi/product_logo_youtube_color_192.png new file mode 100644 index 000000000..374c506cb Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-hdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-hdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-hdpi/product_logo_youtube_color_24.png new file mode 100644 index 000000000..3404cf59d Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-hdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-hdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-hdpi/product_logo_youtube_color_36.png new file mode 100644 index 000000000..cceb29fa8 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-hdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-mdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-mdpi/product_logo_youtube_color_144.png new file mode 100644 index 000000000..6a247917a Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-mdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-mdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-mdpi/product_logo_youtube_color_192.png new file mode 100644 index 000000000..5d2fa41fc Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-mdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-mdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-mdpi/product_logo_youtube_color_24.png new file mode 100644 index 000000000..c21255930 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-mdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-mdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-mdpi/product_logo_youtube_color_36.png new file mode 100644 index 000000000..3404cf59d Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-mdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xhdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xhdpi/product_logo_youtube_color_144.png new file mode 100644 index 000000000..374c506cb Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xhdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xhdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xhdpi/product_logo_youtube_color_192.png new file mode 100644 index 000000000..d22d44f0d Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xhdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xhdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xhdpi/product_logo_youtube_color_24.png new file mode 100644 index 000000000..1464d4906 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xhdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xhdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xhdpi/product_logo_youtube_color_36.png new file mode 100644 index 000000000..f8d1d9e78 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xhdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxhdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxhdpi/product_logo_youtube_color_144.png new file mode 100644 index 000000000..5e270616c Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxhdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxhdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxhdpi/product_logo_youtube_color_192.png new file mode 100644 index 000000000..ded4192bb Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxhdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxhdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxhdpi/product_logo_youtube_color_24.png new file mode 100644 index 000000000..f8d1d9e78 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxhdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxhdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxhdpi/product_logo_youtube_color_36.png new file mode 100644 index 000000000..d699dc653 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxhdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxxhdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxxhdpi/product_logo_youtube_color_144.png new file mode 100644 index 000000000..ded4192bb Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxxhdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxxhdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxxhdpi/product_logo_youtube_color_192.png new file mode 100644 index 000000000..ccdd55661 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxxhdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxxhdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxxhdpi/product_logo_youtube_color_24.png new file mode 100644 index 000000000..304504f96 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxxhdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxxhdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxxhdpi/product_logo_youtube_color_36.png new file mode 100644 index 000000000..6a247917a Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_orange/splash/drawable-xxxhdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable/$avd_anim__0.xml b/src/main/resources/youtube/branding/mmt_orange/splash/drawable/$avd_anim__0.xml new file mode 100644 index 000000000..ed4af3f9f --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_orange/splash/drawable/$avd_anim__0.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable/$avd_anim__1.xml b/src/main/resources/youtube/branding/mmt_orange/splash/drawable/$avd_anim__1.xml new file mode 100644 index 000000000..d429418bf --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_orange/splash/drawable/$avd_anim__1.xml @@ -0,0 +1,10 @@ + + diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable/$avd_anim__2.xml b/src/main/resources/youtube/branding/mmt_orange/splash/drawable/$avd_anim__2.xml new file mode 100644 index 000000000..be41663af --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_orange/splash/drawable/$avd_anim__2.xml @@ -0,0 +1,10 @@ + + diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable/$avd_anim__3.xml b/src/main/resources/youtube/branding/mmt_orange/splash/drawable/$avd_anim__3.xml new file mode 100644 index 000000000..b91965d0c --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_orange/splash/drawable/$avd_anim__3.xml @@ -0,0 +1,11 @@ + + diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable/$avd_anim__4.xml b/src/main/resources/youtube/branding/mmt_orange/splash/drawable/$avd_anim__4.xml new file mode 100644 index 000000000..bd8a269b3 --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_orange/splash/drawable/$avd_anim__4.xml @@ -0,0 +1,11 @@ + + diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/drawable/avd_anim.xml b/src/main/resources/youtube/branding/mmt_orange/splash/drawable/avd_anim.xml new file mode 100644 index 000000000..6a569c5b9 --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_orange/splash/drawable/avd_anim.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/src/main/resources/youtube/branding/mmt_orange/splash/values-v31/styles.xml b/src/main/resources/youtube/branding/mmt_orange/splash/values-v31/styles.xml new file mode 100644 index 000000000..c7462f74a --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_orange/splash/values-v31/styles.xml @@ -0,0 +1,7 @@ + + + + diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-hdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-hdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..d947faf4b Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-hdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-hdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-hdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..b40cc6ddc Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-hdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-hdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-hdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..21a2d3d0a Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-hdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-hdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-hdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..e246d2957 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-hdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-mdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-mdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..d94b6ef64 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-mdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-mdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-mdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..a767d9058 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-mdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-mdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-mdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..0cb610e30 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-mdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-mdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-mdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..b446a6266 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-mdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-xhdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xhdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..fce43e6cc Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xhdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-xhdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xhdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..e4aa2badd Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xhdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-xhdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xhdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..06d965d4f Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xhdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-xhdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xhdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..f090464ba Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xhdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxhdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxhdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..aa64cfc9c Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxhdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxhdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxhdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..726025b57 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxhdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxhdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxhdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..19b69d6dd Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxhdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxhdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxhdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..efbbcc63a Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxhdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxxhdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxxhdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..69e9de7fb Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxxhdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxxhdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxxhdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..0d5458c7b Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxxhdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxxhdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxxhdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..e0217b188 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxxhdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxxhdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxxhdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..7980eba14 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/header/drawable-xxxhdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-hdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-hdpi/adaptiveproduct_youtube_background_color_108.png new file mode 100644 index 000000000..42a6d56e5 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-hdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-hdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-hdpi/adaptiveproduct_youtube_foreground_color_108.png new file mode 100644 index 000000000..5a3952857 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-hdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-hdpi/ic_launcher.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..500e9911c Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-hdpi/ic_launcher.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-hdpi/ic_launcher_round.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 000000000..500e9911c Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-hdpi/ic_launcher_round.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-mdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-mdpi/adaptiveproduct_youtube_background_color_108.png new file mode 100644 index 000000000..51f2f5bcc Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-mdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-mdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-mdpi/adaptiveproduct_youtube_foreground_color_108.png new file mode 100644 index 000000000..40bbc7117 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-mdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-mdpi/ic_launcher.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..c0cced312 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-mdpi/ic_launcher.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-mdpi/ic_launcher_round.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 000000000..c0cced312 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-mdpi/ic_launcher_round.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xhdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xhdpi/adaptiveproduct_youtube_background_color_108.png new file mode 100644 index 000000000..caa231027 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xhdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xhdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xhdpi/adaptiveproduct_youtube_foreground_color_108.png new file mode 100644 index 000000000..fe67e319f Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xhdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xhdpi/ic_launcher.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..b1c006e0d Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xhdpi/ic_launcher.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xhdpi/ic_launcher_round.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 000000000..b1c006e0d Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_background_color_108.png new file mode 100644 index 000000000..c6edf6ec9 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_foreground_color_108.png new file mode 100644 index 000000000..f8d0f0959 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxhdpi/ic_launcher.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..0d37191b9 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxhdpi/ic_launcher_round.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..0d37191b9 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_background_color_108.png new file mode 100644 index 000000000..0f70382df Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_foreground_color_108.png new file mode 100644 index 000000000..83a26922d Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxxhdpi/ic_launcher.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..f877a5da5 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxxhdpi/ic_launcher_round.png b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..f877a5da5 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/launcher/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/monochrome/drawable/adaptive_monochrome_ic_youtube_launcher.xml b/src/main/resources/youtube/branding/mmt_pink/monochrome/drawable/adaptive_monochrome_ic_youtube_launcher.xml new file mode 100644 index 000000000..aec9f0686 --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_pink/monochrome/drawable/adaptive_monochrome_ic_youtube_launcher.xml @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/src/main/resources/youtube/branding/mmt_pink/settings/drawable/revanced_extended_settings_key_icon.xml b/src/main/resources/youtube/branding/mmt_pink/settings/drawable/revanced_extended_settings_key_icon.xml new file mode 100755 index 000000000..142d75dc8 --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_pink/settings/drawable/revanced_extended_settings_key_icon.xml @@ -0,0 +1,926 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-hdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-hdpi/product_logo_youtube_color_144.png new file mode 100644 index 000000000..9ff63e277 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-hdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-hdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-hdpi/product_logo_youtube_color_192.png new file mode 100644 index 000000000..30158ad2e Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-hdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-hdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-hdpi/product_logo_youtube_color_24.png new file mode 100644 index 000000000..76bb83cce Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-hdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-hdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-hdpi/product_logo_youtube_color_36.png new file mode 100644 index 000000000..29545c0d9 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-hdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-mdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-mdpi/product_logo_youtube_color_144.png new file mode 100644 index 000000000..0d37191b9 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-mdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-mdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-mdpi/product_logo_youtube_color_192.png new file mode 100644 index 000000000..dcc3035e8 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-mdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-mdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-mdpi/product_logo_youtube_color_24.png new file mode 100644 index 000000000..b096c4e6d Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-mdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-mdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-mdpi/product_logo_youtube_color_36.png new file mode 100644 index 000000000..76bb83cce Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-mdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xhdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xhdpi/product_logo_youtube_color_144.png new file mode 100644 index 000000000..30158ad2e Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xhdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xhdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xhdpi/product_logo_youtube_color_192.png new file mode 100644 index 000000000..e3ada0e93 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xhdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xhdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xhdpi/product_logo_youtube_color_24.png new file mode 100644 index 000000000..c0cced312 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xhdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xhdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xhdpi/product_logo_youtube_color_36.png new file mode 100644 index 000000000..500e9911c Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xhdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxhdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxhdpi/product_logo_youtube_color_144.png new file mode 100644 index 000000000..5c895e1b2 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxhdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxhdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxhdpi/product_logo_youtube_color_192.png new file mode 100644 index 000000000..5bfb522e9 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxhdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxhdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxhdpi/product_logo_youtube_color_24.png new file mode 100644 index 000000000..500e9911c Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxhdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxhdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxhdpi/product_logo_youtube_color_36.png new file mode 100644 index 000000000..f35eaa175 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxhdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxxhdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxxhdpi/product_logo_youtube_color_144.png new file mode 100644 index 000000000..5bfb522e9 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxxhdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxxhdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxxhdpi/product_logo_youtube_color_192.png new file mode 100644 index 000000000..82870e8af Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxxhdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxxhdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxxhdpi/product_logo_youtube_color_24.png new file mode 100644 index 000000000..b1c006e0d Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxxhdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxxhdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxxhdpi/product_logo_youtube_color_36.png new file mode 100644 index 000000000..0d37191b9 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_pink/splash/drawable-xxxhdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable/$avd_anim__0.xml b/src/main/resources/youtube/branding/mmt_pink/splash/drawable/$avd_anim__0.xml new file mode 100644 index 000000000..c125b6bb0 --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_pink/splash/drawable/$avd_anim__0.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable/$avd_anim__1.xml b/src/main/resources/youtube/branding/mmt_pink/splash/drawable/$avd_anim__1.xml new file mode 100644 index 000000000..d429418bf --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_pink/splash/drawable/$avd_anim__1.xml @@ -0,0 +1,10 @@ + + diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable/$avd_anim__2.xml b/src/main/resources/youtube/branding/mmt_pink/splash/drawable/$avd_anim__2.xml new file mode 100644 index 000000000..be41663af --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_pink/splash/drawable/$avd_anim__2.xml @@ -0,0 +1,10 @@ + + diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable/$avd_anim__3.xml b/src/main/resources/youtube/branding/mmt_pink/splash/drawable/$avd_anim__3.xml new file mode 100644 index 000000000..b91965d0c --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_pink/splash/drawable/$avd_anim__3.xml @@ -0,0 +1,11 @@ + + diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable/$avd_anim__4.xml b/src/main/resources/youtube/branding/mmt_pink/splash/drawable/$avd_anim__4.xml new file mode 100644 index 000000000..bd8a269b3 --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_pink/splash/drawable/$avd_anim__4.xml @@ -0,0 +1,11 @@ + + diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/drawable/avd_anim.xml b/src/main/resources/youtube/branding/mmt_pink/splash/drawable/avd_anim.xml new file mode 100644 index 000000000..6a569c5b9 --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_pink/splash/drawable/avd_anim.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/src/main/resources/youtube/branding/mmt_pink/splash/values-v31/styles.xml b/src/main/resources/youtube/branding/mmt_pink/splash/values-v31/styles.xml new file mode 100644 index 000000000..c7462f74a --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_pink/splash/values-v31/styles.xml @@ -0,0 +1,7 @@ + + + + diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-hdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-hdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..23697c23f Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-hdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-hdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-hdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..2a0c7bdd8 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-hdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-hdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-hdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..303e022d6 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-hdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-hdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-hdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..160f8456c Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-hdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-mdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-mdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..e26dc7429 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-mdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-mdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-mdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..b1d1c0300 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-mdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-mdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-mdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..98ed097f3 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-mdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-mdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-mdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..0f9f944bc Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-mdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xhdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xhdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..a7826dff2 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xhdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xhdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xhdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..79b932e71 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xhdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xhdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xhdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..5da3bed4a Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xhdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xhdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xhdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..c2eff15ce Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xhdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxhdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxhdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..ff65d77b6 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxhdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxhdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxhdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..8fddcd918 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxhdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxhdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxhdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..eaab6cfba Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxhdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxhdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxhdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..c409055b6 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxhdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxxhdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxxhdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..48a6e8199 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxxhdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxxhdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxxhdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..ee3ce8784 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxxhdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxxhdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxxhdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..2bd8e3d1e Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxxhdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxxhdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxxhdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..57547589c Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/header/drawable-xxxhdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-hdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-hdpi/adaptiveproduct_youtube_background_color_108.png new file mode 100644 index 000000000..42a6d56e5 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-hdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-hdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-hdpi/adaptiveproduct_youtube_foreground_color_108.png new file mode 100644 index 000000000..a173b5e5e Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-hdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-hdpi/ic_launcher.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..0669abf9c Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-hdpi/ic_launcher.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-hdpi/ic_launcher_round.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 000000000..0669abf9c Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-hdpi/ic_launcher_round.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-mdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-mdpi/adaptiveproduct_youtube_background_color_108.png new file mode 100644 index 000000000..51f2f5bcc Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-mdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-mdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-mdpi/adaptiveproduct_youtube_foreground_color_108.png new file mode 100644 index 000000000..b9da67dc7 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-mdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-mdpi/ic_launcher.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..651a02fd7 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-mdpi/ic_launcher.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-mdpi/ic_launcher_round.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 000000000..651a02fd7 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-mdpi/ic_launcher_round.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xhdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xhdpi/adaptiveproduct_youtube_background_color_108.png new file mode 100644 index 000000000..caa231027 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xhdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xhdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xhdpi/adaptiveproduct_youtube_foreground_color_108.png new file mode 100644 index 000000000..decbef3eb Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xhdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xhdpi/ic_launcher.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..6bc5440cb Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xhdpi/ic_launcher.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xhdpi/ic_launcher_round.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 000000000..6bc5440cb Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_background_color_108.png new file mode 100644 index 000000000..c6edf6ec9 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_foreground_color_108.png new file mode 100644 index 000000000..3c547f94b Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxhdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxhdpi/ic_launcher.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..c15d43850 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxhdpi/ic_launcher_round.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..c15d43850 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_background_color_108.png new file mode 100644 index 000000000..0f70382df Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_background_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_foreground_color_108.png new file mode 100644 index 000000000..e5aee54f6 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/adaptiveproduct_youtube_foreground_color_108.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/ic_launcher.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..83ce3c6fb Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/ic_launcher_round.png b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..83ce3c6fb Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/launcher/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/monochrome/drawable/adaptive_monochrome_ic_youtube_launcher.xml b/src/main/resources/youtube/branding/mmt_turquoise/monochrome/drawable/adaptive_monochrome_ic_youtube_launcher.xml new file mode 100644 index 000000000..aec9f0686 --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_turquoise/monochrome/drawable/adaptive_monochrome_ic_youtube_launcher.xml @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/src/main/resources/youtube/branding/mmt_turquoise/settings/drawable/revanced_extended_settings_key_icon.xml b/src/main/resources/youtube/branding/mmt_turquoise/settings/drawable/revanced_extended_settings_key_icon.xml new file mode 100755 index 000000000..5265f69ea --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_turquoise/settings/drawable/revanced_extended_settings_key_icon.xml @@ -0,0 +1,1038 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-hdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-hdpi/product_logo_youtube_color_144.png new file mode 100644 index 000000000..b5b84787d Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-hdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-hdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-hdpi/product_logo_youtube_color_192.png new file mode 100644 index 000000000..3e89b394d Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-hdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-hdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-hdpi/product_logo_youtube_color_24.png new file mode 100644 index 000000000..bf7093f75 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-hdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-hdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-hdpi/product_logo_youtube_color_36.png new file mode 100644 index 000000000..1e9d5b257 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-hdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-mdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-mdpi/product_logo_youtube_color_144.png new file mode 100644 index 000000000..c15d43850 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-mdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-mdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-mdpi/product_logo_youtube_color_192.png new file mode 100644 index 000000000..83ce3c6fb Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-mdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-mdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-mdpi/product_logo_youtube_color_24.png new file mode 100644 index 000000000..f74fcf1ef Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-mdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-mdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-mdpi/product_logo_youtube_color_36.png new file mode 100644 index 000000000..bf7093f75 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-mdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xhdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xhdpi/product_logo_youtube_color_144.png new file mode 100644 index 000000000..3e89b394d Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xhdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xhdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xhdpi/product_logo_youtube_color_192.png new file mode 100644 index 000000000..c185b6766 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xhdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xhdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xhdpi/product_logo_youtube_color_24.png new file mode 100644 index 000000000..651a02fd7 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xhdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xhdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xhdpi/product_logo_youtube_color_36.png new file mode 100644 index 000000000..0669abf9c Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xhdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxhdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxhdpi/product_logo_youtube_color_144.png new file mode 100644 index 000000000..e04c41c29 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxhdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxhdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxhdpi/product_logo_youtube_color_192.png new file mode 100644 index 000000000..981101ba7 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxhdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxhdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxhdpi/product_logo_youtube_color_24.png new file mode 100644 index 000000000..0669abf9c Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxhdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxhdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxhdpi/product_logo_youtube_color_36.png new file mode 100644 index 000000000..889e7dd2c Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxhdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxxhdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxxhdpi/product_logo_youtube_color_144.png new file mode 100644 index 000000000..981101ba7 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxxhdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxxhdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxxhdpi/product_logo_youtube_color_192.png new file mode 100644 index 000000000..16e812324 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxxhdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxxhdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxxhdpi/product_logo_youtube_color_24.png new file mode 100644 index 000000000..6bc5440cb Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxxhdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxxhdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxxhdpi/product_logo_youtube_color_36.png new file mode 100644 index 000000000..c15d43850 Binary files /dev/null and b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable-xxxhdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable/$avd_anim__0.xml b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable/$avd_anim__0.xml new file mode 100644 index 000000000..c8b35c56a --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable/$avd_anim__0.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable/$avd_anim__1.xml b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable/$avd_anim__1.xml new file mode 100644 index 000000000..d429418bf --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable/$avd_anim__1.xml @@ -0,0 +1,10 @@ + + diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable/$avd_anim__2.xml b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable/$avd_anim__2.xml new file mode 100644 index 000000000..be41663af --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable/$avd_anim__2.xml @@ -0,0 +1,10 @@ + + diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable/$avd_anim__3.xml b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable/$avd_anim__3.xml new file mode 100644 index 000000000..b91965d0c --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable/$avd_anim__3.xml @@ -0,0 +1,11 @@ + + diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable/$avd_anim__4.xml b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable/$avd_anim__4.xml new file mode 100644 index 000000000..bd8a269b3 --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable/$avd_anim__4.xml @@ -0,0 +1,11 @@ + + diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable/avd_anim.xml b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable/avd_anim.xml new file mode 100644 index 000000000..6a569c5b9 --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_turquoise/splash/drawable/avd_anim.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/src/main/resources/youtube/branding/mmt_turquoise/splash/values-v31/styles.xml b/src/main/resources/youtube/branding/mmt_turquoise/splash/values-v31/styles.xml new file mode 100644 index 000000000..c7462f74a --- /dev/null +++ b/src/main/resources/youtube/branding/mmt_turquoise/splash/values-v31/styles.xml @@ -0,0 +1,7 @@ + + + + diff --git a/src/main/resources/youtube/branding/revancify_blue/settings/drawable/revanced_extended_settings_key_icon.xml b/src/main/resources/youtube/branding/revancify_blue/settings/drawable/revanced_extended_settings_key_icon.xml index c088bcfcc..5f052277f 100644 --- a/src/main/resources/youtube/branding/revancify_blue/settings/drawable/revanced_extended_settings_key_icon.xml +++ b/src/main/resources/youtube/branding/revancify_blue/settings/drawable/revanced_extended_settings_key_icon.xml @@ -1,1034 +1,33 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + xmlns:android="http://schemas.android.com/apk/res/android" + android:name="vector" + android:width="48dp" + android:height="48dp" + android:viewportWidth="384" + android:viewportHeight="384"> + + + + + diff --git a/src/main/resources/youtube/branding/revancify_red/settings/drawable/revanced_extended_settings_key_icon.xml b/src/main/resources/youtube/branding/revancify_red/settings/drawable/revanced_extended_settings_key_icon.xml index 98cfb9ccc..668ea4cc6 100644 --- a/src/main/resources/youtube/branding/revancify_red/settings/drawable/revanced_extended_settings_key_icon.xml +++ b/src/main/resources/youtube/branding/revancify_red/settings/drawable/revanced_extended_settings_key_icon.xml @@ -1,1026 +1,33 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + xmlns:android="http://schemas.android.com/apk/res/android" + android:name="vector" + android:width="48dp" + android:height="48dp" + android:viewportWidth="384" + android:viewportHeight="384"> + + + + + diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-hdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-hdpi/product_logo_youtube_color_144.png index 59d9c788b..969e42048 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-hdpi/product_logo_youtube_color_144.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-hdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-hdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-hdpi/product_logo_youtube_color_192.png index 842de2040..7de09c0fe 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-hdpi/product_logo_youtube_color_192.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-hdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-hdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-hdpi/product_logo_youtube_color_24.png index 04e2ba7c0..93bd0313b 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-hdpi/product_logo_youtube_color_24.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-hdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-hdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-hdpi/product_logo_youtube_color_36.png index d197ce496..432a24c5a 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-hdpi/product_logo_youtube_color_36.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-hdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-mdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-mdpi/product_logo_youtube_color_144.png index defe1077a..20661ce6b 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-mdpi/product_logo_youtube_color_144.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-mdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-mdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-mdpi/product_logo_youtube_color_192.png index b887a004d..c84468827 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-mdpi/product_logo_youtube_color_192.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-mdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-mdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-mdpi/product_logo_youtube_color_24.png index cbd532eda..764225a5d 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-mdpi/product_logo_youtube_color_24.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-mdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-mdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-mdpi/product_logo_youtube_color_36.png index cd8103fb8..93bd0313b 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-mdpi/product_logo_youtube_color_36.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-mdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xhdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xhdpi/product_logo_youtube_color_144.png index 7ca77f4df..7de09c0fe 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xhdpi/product_logo_youtube_color_144.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xhdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xhdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xhdpi/product_logo_youtube_color_192.png index bd8a86e48..8c1c450e7 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xhdpi/product_logo_youtube_color_192.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xhdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xhdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xhdpi/product_logo_youtube_color_24.png index 032f12897..0ac890ca9 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xhdpi/product_logo_youtube_color_24.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xhdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xhdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xhdpi/product_logo_youtube_color_36.png index 2deaa9011..ab2bd90a6 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xhdpi/product_logo_youtube_color_36.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xhdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxhdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxhdpi/product_logo_youtube_color_144.png index 85cab5838..ab87706ac 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxhdpi/product_logo_youtube_color_144.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxhdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxhdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxhdpi/product_logo_youtube_color_192.png index abf3e4485..e86818523 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxhdpi/product_logo_youtube_color_192.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxhdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxhdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxhdpi/product_logo_youtube_color_24.png index 551561653..ab2bd90a6 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxhdpi/product_logo_youtube_color_24.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxhdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxhdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxhdpi/product_logo_youtube_color_36.png index 106e7ba4c..6ff995245 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxhdpi/product_logo_youtube_color_36.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxhdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxxhdpi/product_logo_youtube_color_144.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxxhdpi/product_logo_youtube_color_144.png index 59ae6c7cf..e86818523 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxxhdpi/product_logo_youtube_color_144.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxxhdpi/product_logo_youtube_color_144.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxxhdpi/product_logo_youtube_color_192.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxxhdpi/product_logo_youtube_color_192.png index 0f6c5a2e7..0ae02ab00 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxxhdpi/product_logo_youtube_color_192.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxxhdpi/product_logo_youtube_color_192.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxxhdpi/product_logo_youtube_color_24.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxxhdpi/product_logo_youtube_color_24.png index 967f66673..b8d04643a 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxxhdpi/product_logo_youtube_color_24.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxxhdpi/product_logo_youtube_color_24.png differ diff --git a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxxhdpi/product_logo_youtube_color_36.png b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxxhdpi/product_logo_youtube_color_36.png index dfccd7b78..20661ce6b 100644 Binary files a/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxxhdpi/product_logo_youtube_color_36.png and b/src/main/resources/youtube/branding/xisr_yellow/splash/drawable-xxxhdpi/product_logo_youtube_color_36.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-hdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-hdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..5ba804ae0 Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-hdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-hdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-hdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..5ba804ae0 Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-hdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-hdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-hdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..5ba804ae0 Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-hdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-hdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-hdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..5ba804ae0 Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-hdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-mdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-mdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..3542f98f5 Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-mdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-mdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-mdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..3542f98f5 Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-mdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-mdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-mdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..3542f98f5 Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-mdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-mdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-mdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..3542f98f5 Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-mdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xhdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xhdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..c12303a7d Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xhdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xhdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xhdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..c12303a7d Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xhdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xhdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xhdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..c12303a7d Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xhdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xhdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xhdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..c12303a7d Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xhdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxhdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxhdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..aece8cfd9 Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxhdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxhdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxhdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..aece8cfd9 Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxhdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxhdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxhdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..aece8cfd9 Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxhdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxhdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxhdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..aece8cfd9 Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxhdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxxhdpi/yt_premium_wordmark_header_dark.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxxhdpi/yt_premium_wordmark_header_dark.png new file mode 100644 index 000000000..0ba37b7c0 Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxxhdpi/yt_premium_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxxhdpi/yt_premium_wordmark_header_light.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxxhdpi/yt_premium_wordmark_header_light.png new file mode 100644 index 000000000..0ba37b7c0 Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxxhdpi/yt_premium_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxxhdpi/yt_wordmark_header_dark.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxxhdpi/yt_wordmark_header_dark.png new file mode 100644 index 000000000..0ba37b7c0 Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxxhdpi/yt_wordmark_header_dark.png differ diff --git a/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxxhdpi/yt_wordmark_header_light.png b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxxhdpi/yt_wordmark_header_light.png new file mode 100644 index 000000000..0ba37b7c0 Binary files /dev/null and b/src/main/resources/youtube/branding/youtube_minimal_header/header/drawable-xxxhdpi/yt_wordmark_header_light.png differ diff --git a/src/main/resources/youtube/overlaybuttons/bold/drawable-hdpi/yt_outline_chevron_down_white_24.png b/src/main/resources/youtube/overlaybuttons/bold/drawable-hdpi/yt_outline_chevron_down_white_24.png index 075578341..8a170e6b0 100644 Binary files a/src/main/resources/youtube/overlaybuttons/bold/drawable-hdpi/yt_outline_chevron_down_white_24.png and b/src/main/resources/youtube/overlaybuttons/bold/drawable-hdpi/yt_outline_chevron_down_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/bold/drawable-mdpi/yt_outline_chevron_down_white_24.png b/src/main/resources/youtube/overlaybuttons/bold/drawable-mdpi/yt_outline_chevron_down_white_24.png index 199c7c89b..83b64b09e 100644 Binary files a/src/main/resources/youtube/overlaybuttons/bold/drawable-mdpi/yt_outline_chevron_down_white_24.png and b/src/main/resources/youtube/overlaybuttons/bold/drawable-mdpi/yt_outline_chevron_down_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/bold/drawable-xhdpi/yt_outline_chevron_down_white_24.png b/src/main/resources/youtube/overlaybuttons/bold/drawable-xhdpi/yt_outline_chevron_down_white_24.png index 2176d1095..706dffc6d 100644 Binary files a/src/main/resources/youtube/overlaybuttons/bold/drawable-xhdpi/yt_outline_chevron_down_white_24.png and b/src/main/resources/youtube/overlaybuttons/bold/drawable-xhdpi/yt_outline_chevron_down_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/bold/drawable-xxhdpi/yt_outline_chevron_down_white_24.png b/src/main/resources/youtube/overlaybuttons/bold/drawable-xxhdpi/yt_outline_chevron_down_white_24.png index 7e210f49c..0f95178bc 100644 Binary files a/src/main/resources/youtube/overlaybuttons/bold/drawable-xxhdpi/yt_outline_chevron_down_white_24.png and b/src/main/resources/youtube/overlaybuttons/bold/drawable-xxhdpi/yt_outline_chevron_down_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/bold/drawable-xxxhdpi/yt_outline_chevron_down_white_24.png b/src/main/resources/youtube/overlaybuttons/bold/drawable-xxxhdpi/yt_outline_chevron_down_white_24.png index 325c0e2e6..409e468b0 100644 Binary files a/src/main/resources/youtube/overlaybuttons/bold/drawable-xxxhdpi/yt_outline_chevron_down_white_24.png and b/src/main/resources/youtube/overlaybuttons/bold/drawable-xxxhdpi/yt_outline_chevron_down_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/rounded/drawable-hdpi/yt_outline_chevron_down_white_24.png b/src/main/resources/youtube/overlaybuttons/rounded/drawable-hdpi/yt_outline_chevron_down_white_24.png index cc9857401..841f74500 100644 Binary files a/src/main/resources/youtube/overlaybuttons/rounded/drawable-hdpi/yt_outline_chevron_down_white_24.png and b/src/main/resources/youtube/overlaybuttons/rounded/drawable-hdpi/yt_outline_chevron_down_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/rounded/drawable-mdpi/yt_outline_chevron_down_white_24.png b/src/main/resources/youtube/overlaybuttons/rounded/drawable-mdpi/yt_outline_chevron_down_white_24.png index 221be027b..2cc43530b 100644 Binary files a/src/main/resources/youtube/overlaybuttons/rounded/drawable-mdpi/yt_outline_chevron_down_white_24.png and b/src/main/resources/youtube/overlaybuttons/rounded/drawable-mdpi/yt_outline_chevron_down_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/rounded/drawable-xhdpi/yt_outline_chevron_down_white_24.png b/src/main/resources/youtube/overlaybuttons/rounded/drawable-xhdpi/yt_outline_chevron_down_white_24.png index fda197531..a396bb487 100644 Binary files a/src/main/resources/youtube/overlaybuttons/rounded/drawable-xhdpi/yt_outline_chevron_down_white_24.png and b/src/main/resources/youtube/overlaybuttons/rounded/drawable-xhdpi/yt_outline_chevron_down_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/rounded/drawable-xxhdpi/yt_outline_chevron_down_white_24.png b/src/main/resources/youtube/overlaybuttons/rounded/drawable-xxhdpi/yt_outline_chevron_down_white_24.png index 1e590d18b..a4554b936 100644 Binary files a/src/main/resources/youtube/overlaybuttons/rounded/drawable-xxhdpi/yt_outline_chevron_down_white_24.png and b/src/main/resources/youtube/overlaybuttons/rounded/drawable-xxhdpi/yt_outline_chevron_down_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/rounded/drawable-xxxhdpi/yt_outline_chevron_down_white_24.png b/src/main/resources/youtube/overlaybuttons/rounded/drawable-xxxhdpi/yt_outline_chevron_down_white_24.png index f361f09c1..c7f8516c9 100644 Binary files a/src/main/resources/youtube/overlaybuttons/rounded/drawable-xxxhdpi/yt_outline_chevron_down_white_24.png and b/src/main/resources/youtube/overlaybuttons/rounded/drawable-xxxhdpi/yt_outline_chevron_down_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_closed_caption_off_grey600_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_closed_caption_off_grey600_24.png index 6a7c881f3..63a60fd14 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_closed_caption_off_grey600_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_closed_caption_off_grey600_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_fullscreen_exit_grey600_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_fullscreen_exit_grey600_24.png index e8264dfb1..0eebd1426 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_fullscreen_exit_grey600_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_fullscreen_exit_grey600_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_fullscreen_exit_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_fullscreen_exit_white_24.png index e8264dfb1..0eebd1426 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_fullscreen_exit_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_fullscreen_exit_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_fullscreen_grey600_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_fullscreen_grey600_24.png index b4fda997b..77f34b5db 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_fullscreen_grey600_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_fullscreen_grey600_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_fullscreen_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_fullscreen_white_24.png index b4fda997b..77f34b5db 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_fullscreen_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/quantum_ic_fullscreen_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_copy_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_copy_button.png index 927583ecf..32b55f444 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_copy_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_copy_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_copy_timestamp_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_copy_timestamp_button.png index 918455b43..fbe9363cb 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_copy_timestamp_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_copy_timestamp_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_download_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_download_button.png index 20f5080b2..a718e0430 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_download_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_download_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_speed_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_speed_button.png index 8db5c39c6..c8aa0cf49 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_speed_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_speed_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_time_ordered_playlist_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_time_ordered_playlist_button.png index aaf0e5847..78e2d95a1 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_time_ordered_playlist_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_time_ordered_playlist_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_volume_muted_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_volume_muted_button.png index f73cd1ed7..c159a73be 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_volume_muted_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_volume_muted_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_volume_unmuted_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_volume_unmuted_button.png index 519fb948e..958739066 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_volume_unmuted_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_volume_unmuted_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_whitelist_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_whitelist_button.png index b7d6944ce..9abe2ea55 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_whitelist_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/revanced_whitelist_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_fill_arrow_repeat_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_fill_arrow_repeat_white_24.png index 4038650e2..12923a141 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_fill_arrow_repeat_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_fill_arrow_repeat_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_arrow_repeat_1_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_arrow_repeat_1_white_24.png index dd6307c76..e50414c3f 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_arrow_repeat_1_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_arrow_repeat_1_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_arrow_shuffle_1_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_arrow_shuffle_1_white_24.png index 291c0c801..829a094b3 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_arrow_shuffle_1_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_arrow_shuffle_1_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_gear_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_gear_white_24.png index 362e44846..72dfbb678 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_gear_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_gear_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_screen_full_exit_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_screen_full_exit_white_24.png index e8264dfb1..0eebd1426 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_screen_full_exit_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_screen_full_exit_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_screen_full_vd_theme_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_screen_full_vd_theme_24.png index b4fda997b..77f34b5db 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_screen_full_vd_theme_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_screen_full_vd_theme_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_screen_full_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_screen_full_white_24.png index b4fda997b..77f34b5db 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_screen_full_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-hdpi/yt_outline_screen_full_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_closed_caption_off_grey600_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_closed_caption_off_grey600_24.png index 9a9a3ab0b..aea913be0 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_closed_caption_off_grey600_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_closed_caption_off_grey600_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_fullscreen_exit_grey600_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_fullscreen_exit_grey600_24.png index 938ae850e..05b181ddf 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_fullscreen_exit_grey600_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_fullscreen_exit_grey600_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_fullscreen_exit_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_fullscreen_exit_white_24.png index 938ae850e..05b181ddf 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_fullscreen_exit_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_fullscreen_exit_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_fullscreen_grey600_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_fullscreen_grey600_24.png index a1ffad665..dd0dbdd7b 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_fullscreen_grey600_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_fullscreen_grey600_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_fullscreen_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_fullscreen_white_24.png index a1ffad665..dd0dbdd7b 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_fullscreen_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/quantum_ic_fullscreen_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_copy_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_copy_button.png index ae6d26ddb..a4c1f7a42 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_copy_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_copy_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_copy_timestamp_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_copy_timestamp_button.png index 8b3b6d396..11f6caa46 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_copy_timestamp_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_copy_timestamp_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_download_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_download_button.png index e4f097586..f2e94b632 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_download_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_download_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_speed_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_speed_button.png index 62be6a185..4d29921ec 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_speed_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_speed_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_time_ordered_playlist_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_time_ordered_playlist_button.png index 97aa46f6e..7e1ede97d 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_time_ordered_playlist_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_time_ordered_playlist_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_volume_muted_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_volume_muted_button.png index 571c33a78..8021c10cc 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_volume_muted_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_volume_muted_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_volume_unmuted_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_volume_unmuted_button.png index 5f5751d9b..88fca71bb 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_volume_unmuted_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_volume_unmuted_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_whitelist_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_whitelist_button.png index 6c7c8072e..33eb897c1 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_whitelist_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/revanced_whitelist_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_fill_arrow_repeat_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_fill_arrow_repeat_white_24.png index b2b2e6f44..dfdfac899 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_fill_arrow_repeat_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_fill_arrow_repeat_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_arrow_repeat_1_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_arrow_repeat_1_white_24.png index 4a75adfae..0ad8dd95d 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_arrow_repeat_1_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_arrow_repeat_1_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_arrow_shuffle_1_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_arrow_shuffle_1_white_24.png index dd1ef8145..3848d2379 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_arrow_shuffle_1_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_arrow_shuffle_1_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_gear_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_gear_white_24.png index 2b6815f58..92e3f1ec4 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_gear_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_gear_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_screen_full_exit_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_screen_full_exit_white_24.png index 938ae850e..05b181ddf 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_screen_full_exit_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_screen_full_exit_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_screen_full_vd_theme_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_screen_full_vd_theme_24.png index a1ffad665..dd0dbdd7b 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_screen_full_vd_theme_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_screen_full_vd_theme_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_screen_full_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_screen_full_white_24.png index a1ffad665..dd0dbdd7b 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_screen_full_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-mdpi/yt_outline_screen_full_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_closed_caption_off_grey600_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_closed_caption_off_grey600_24.png index 6c2e3d6e5..57aea8576 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_closed_caption_off_grey600_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_closed_caption_off_grey600_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_fullscreen_exit_grey600_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_fullscreen_exit_grey600_24.png index d631ae0d3..659800f49 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_fullscreen_exit_grey600_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_fullscreen_exit_grey600_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_fullscreen_exit_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_fullscreen_exit_white_24.png index d631ae0d3..659800f49 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_fullscreen_exit_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_fullscreen_exit_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_fullscreen_grey600_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_fullscreen_grey600_24.png index e4702e744..aaa5d8d2a 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_fullscreen_grey600_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_fullscreen_grey600_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_fullscreen_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_fullscreen_white_24.png index e4702e744..aaa5d8d2a 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_fullscreen_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/quantum_ic_fullscreen_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_copy_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_copy_button.png index 4a417b065..c38dc4ff8 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_copy_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_copy_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_copy_timestamp_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_copy_timestamp_button.png index f9b2fce71..9b9eb08dc 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_copy_timestamp_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_copy_timestamp_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_download_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_download_button.png index 7ee1a52af..082425a6d 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_download_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_download_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_speed_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_speed_button.png index 222f3495f..f4aea11b0 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_speed_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_speed_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_time_ordered_playlist_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_time_ordered_playlist_button.png index a6eb2c90a..b15ed49c7 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_time_ordered_playlist_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_time_ordered_playlist_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_volume_muted_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_volume_muted_button.png index a80d65d28..d00bace28 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_volume_muted_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_volume_muted_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_volume_unmuted_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_volume_unmuted_button.png index e9c207ab3..5ee0b5dbe 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_volume_unmuted_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_volume_unmuted_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_whitelist_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_whitelist_button.png index 3d8403fcc..bac0af80d 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_whitelist_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/revanced_whitelist_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_fill_arrow_repeat_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_fill_arrow_repeat_white_24.png index 8265eb714..196cb7e07 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_fill_arrow_repeat_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_fill_arrow_repeat_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_arrow_repeat_1_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_arrow_repeat_1_white_24.png index 27289d274..971aaed40 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_arrow_repeat_1_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_arrow_repeat_1_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_arrow_shuffle_1_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_arrow_shuffle_1_white_24.png index cdc76769a..a4651b94f 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_arrow_shuffle_1_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_arrow_shuffle_1_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_gear_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_gear_white_24.png index 097ca76a8..d36e48595 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_gear_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_gear_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_screen_full_exit_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_screen_full_exit_white_24.png index d631ae0d3..659800f49 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_screen_full_exit_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_screen_full_exit_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_screen_full_vd_theme_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_screen_full_vd_theme_24.png index e4702e744..aaa5d8d2a 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_screen_full_vd_theme_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_screen_full_vd_theme_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_screen_full_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_screen_full_white_24.png index e4702e744..aaa5d8d2a 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_screen_full_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xhdpi/yt_outline_screen_full_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_closed_caption_off_grey600_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_closed_caption_off_grey600_24.png index 2b5bb5d8e..a8841ce35 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_closed_caption_off_grey600_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_closed_caption_off_grey600_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_fullscreen_exit_grey600_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_fullscreen_exit_grey600_24.png index ec962d35e..a74831b0e 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_fullscreen_exit_grey600_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_fullscreen_exit_grey600_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_fullscreen_exit_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_fullscreen_exit_white_24.png index ec962d35e..a74831b0e 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_fullscreen_exit_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_fullscreen_exit_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_fullscreen_grey600_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_fullscreen_grey600_24.png index 87eb4b20e..92da603e3 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_fullscreen_grey600_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_fullscreen_grey600_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_fullscreen_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_fullscreen_white_24.png index 87eb4b20e..92da603e3 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_fullscreen_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/quantum_ic_fullscreen_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_copy_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_copy_button.png index dddff2044..6c24fea60 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_copy_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_copy_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_copy_timestamp_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_copy_timestamp_button.png index f4032b711..1fd743698 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_copy_timestamp_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_copy_timestamp_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_download_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_download_button.png index 7414a3d62..9a07c87d6 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_download_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_download_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_speed_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_speed_button.png index 976cfda93..3bf00876f 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_speed_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_speed_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_time_ordered_playlist_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_time_ordered_playlist_button.png index cf45b643c..a91f5de19 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_time_ordered_playlist_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_time_ordered_playlist_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_volume_muted_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_volume_muted_button.png index 620286389..600c4cde1 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_volume_muted_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_volume_muted_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_volume_unmuted_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_volume_unmuted_button.png index 9dc60eef6..55a0e86bd 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_volume_unmuted_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_volume_unmuted_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_whitelist_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_whitelist_button.png index c75eb21bf..420b0002a 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_whitelist_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/revanced_whitelist_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_fill_arrow_repeat_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_fill_arrow_repeat_white_24.png index e7fa8c7c5..62d7a88c6 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_fill_arrow_repeat_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_fill_arrow_repeat_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_arrow_repeat_1_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_arrow_repeat_1_white_24.png index 8fe13239c..252f18deb 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_arrow_repeat_1_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_arrow_repeat_1_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_arrow_shuffle_1_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_arrow_shuffle_1_white_24.png index f7471cec2..14a51d4b0 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_arrow_shuffle_1_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_arrow_shuffle_1_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_screen_full_exit_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_screen_full_exit_white_24.png index ec962d35e..a74831b0e 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_screen_full_exit_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_screen_full_exit_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_screen_full_vd_theme_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_screen_full_vd_theme_24.png index 87eb4b20e..92da603e3 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_screen_full_vd_theme_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_screen_full_vd_theme_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_screen_full_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_screen_full_white_24.png index 87eb4b20e..92da603e3 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_screen_full_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxhdpi/yt_outline_screen_full_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_closed_caption_off_grey600_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_closed_caption_off_grey600_24.png index 777d3eea9..97b21237a 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_closed_caption_off_grey600_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_closed_caption_off_grey600_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_fullscreen_exit_grey600_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_fullscreen_exit_grey600_24.png index 80336495b..c8f95d9d7 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_fullscreen_exit_grey600_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_fullscreen_exit_grey600_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_fullscreen_exit_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_fullscreen_exit_white_24.png index 80336495b..c8f95d9d7 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_fullscreen_exit_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_fullscreen_exit_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_fullscreen_grey600_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_fullscreen_grey600_24.png index 4f4c275c5..69678d1f9 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_fullscreen_grey600_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_fullscreen_grey600_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_fullscreen_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_fullscreen_white_24.png index 4f4c275c5..69678d1f9 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_fullscreen_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/quantum_ic_fullscreen_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_copy_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_copy_button.png index 2c31ba6ff..64a5365ed 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_copy_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_copy_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_copy_timestamp_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_copy_timestamp_button.png index 0373d475d..7990c8d78 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_copy_timestamp_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_copy_timestamp_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_download_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_download_button.png index b94deec44..405950982 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_download_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_download_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_speed_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_speed_button.png index 4f8d1a708..3feb6b89f 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_speed_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_speed_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_time_ordered_playlist_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_time_ordered_playlist_button.png index 0091681e0..e191c4012 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_time_ordered_playlist_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_time_ordered_playlist_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_volume_muted_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_volume_muted_button.png index 30f27512d..72d882522 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_volume_muted_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_volume_muted_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_volume_unmuted_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_volume_unmuted_button.png index 3a0a8d9d0..8be2cec91 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_volume_unmuted_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_volume_unmuted_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_whitelist_button.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_whitelist_button.png index f4e230bd3..9906823d1 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_whitelist_button.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/revanced_whitelist_button.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_fill_arrow_repeat_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_fill_arrow_repeat_white_24.png index f851bdd84..48a0a5c42 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_fill_arrow_repeat_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_fill_arrow_repeat_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_arrow_repeat_1_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_arrow_repeat_1_white_24.png index a452e3fd2..5e111d74f 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_arrow_repeat_1_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_arrow_repeat_1_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_arrow_shuffle_1_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_arrow_shuffle_1_white_24.png index 8f49a1952..b609ce574 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_arrow_shuffle_1_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_arrow_shuffle_1_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_screen_full_exit_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_screen_full_exit_white_24.png index 80336495b..c8f95d9d7 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_screen_full_exit_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_screen_full_exit_white_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_screen_full_vd_theme_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_screen_full_vd_theme_24.png index 4f4c275c5..69678d1f9 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_screen_full_vd_theme_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_screen_full_vd_theme_24.png differ diff --git a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_screen_full_white_24.png b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_screen_full_white_24.png index 4f4c275c5..69678d1f9 100644 Binary files a/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_screen_full_white_24.png and b/src/main/resources/youtube/overlaybuttons/thin/drawable-xxxhdpi/yt_outline_screen_full_white_24.png differ diff --git a/src/main/resources/youtube/settings/host/values/arrays.xml b/src/main/resources/youtube/settings/host/values/arrays.xml index 40854ae62..6c1224f35 100644 --- a/src/main/resources/youtube/settings/host/values/arrays.xml +++ b/src/main/resources/youtube/settings/host/values/arrays.xml @@ -25,9 +25,9 @@ @string/revanced_change_start_page_entry_default @string/revanced_change_start_page_entry_search + @string/revanced_change_start_page_entry_shorts @string/revanced_change_start_page_entry_subscriptions @string/revanced_change_start_page_entry_explore - @string/revanced_change_start_page_entry_shorts @string/revanced_change_start_page_entry_library @string/revanced_change_start_page_entry_liked_videos @string/revanced_change_start_page_entry_watch_later @@ -39,30 +39,28 @@ @string/revanced_change_start_page_entry_movies @string/revanced_change_start_page_entry_sports @string/revanced_change_start_page_entry_browse - @string/revanced_change_start_page_entry_playables @string/revanced_change_start_page_entry_courses - - - open.search - open.subscriptions - open.explore - open.shorts - - www.youtube.com/feed/library - www.youtube.com/playlist?list=LL - www.youtube.com/playlist?list=WL - www.youtube.com/feed/history - www.youtube.com/feed/trending - www.youtube.com/gaming - www.youtube.com/channel/UC4R8DWoMoI7CAwX8_LjQHig - www.youtube.com/channel/UC-9-kyTW8ZkZNDHQJ6FgpwQ - www.youtube.com/feed/storefront?bp=ogUCKAI%3D - www.youtube.com/channel/UCEgdi0XIXXZ-qJOFPf4JSKw - www.youtube.com/feed/guide_builder - www.youtube.com/playables - www.youtube.com/channel/UCtFRv9O2AHqOZjjynzrv-xg + ORIGINAL + + SEARCH + SHORTS + + SUBSCRIPTIONS + EXPLORE + LIBRARY + LIKED_VIDEO + WATCH_LATER + HISTORY + TRENDING + GAMING + LIVE + MUSIC + MOVIE + SPORTS + BROWSE + COURSES @string/revanced_change_shorts_repeat_state_entry_default @@ -207,6 +205,24 @@ 17.41.37 17.33.42 + + YouTube Music + + + com.google.android.apps.youtube.music + + + -1 + 0 + +1 + +2 + + + -1 + 0 + 1 + 2 + @string/revanced_watch_history_type_entry_1 @string/revanced_watch_history_type_entry_2 diff --git a/src/main/resources/youtube/settings/host/values/strings.xml b/src/main/resources/youtube/settings/host/values/strings.xml index 67ba617b7..1dcfe77d8 100644 --- a/src/main/resources/youtube/settings/host/values/strings.xml +++ b/src/main/resources/youtube/settings/host/values/strings.xml @@ -23,6 +23,7 @@ If enabled, video URLs will be sent to the API server and no other data is sent. Tap here to learn more about DeArrow." DeArrow + Invalid DeArrow API URL. The URL of the DeArrow thumbnail cache endpoint. DeArrow API endpoint Toast is not shown if DeArrow is unavailable. @@ -85,15 +86,18 @@ Tap here to learn more about DeArrow." Live Movies Music - Playables Search Shorts Sports Subscriptions Trending Watch later - Invalid start page, resetting to default. Change start page + Start page changes only once. + "Start page always changes. + +Limitation: Back button on the toolbar may not work." + Change start page type Generic header is enabled. Premium header is enabled. Change YouTube header @@ -106,11 +110,11 @@ Tap here to learn more about DeArrow." Old style flyout menu is used. Custom dialog is used. Custom playback speed menu type - Custom speeds must be less than %sx. Using default values. - Invalid custom playback speeds. Using default values. + Custom speeds must be less than %sx. + Invalid custom playback speeds. Add or change available playback speeds. Edit custom playback speeds - Player overlay opacity must be between 0-100. Reset to default values. + Player overlay opacity must be between 0-100. Opacity value between 0-100, where 0 is transparent. Custom player overlay opacity Type the hex code of the seekbar color. @@ -190,6 +194,9 @@ Limitation: This setting may not apply to videos that do not include the 'Listen Rolling numbers are animated. Rolling numbers are not animated. Disable Rolling number animations + Fountain animation is enabled above the Like button. + Fountain animation is disabled above the Like button. + Disable Like button animation "Disable '2x>>' while holding down. Note: @@ -209,7 +216,7 @@ Note: • Maximum resolution is 1080p. • Video playback will use more internet data than VP9. -• To get HDR playback, HDR video still uses the VP9 codec." +• VP9 codec is still used for HDR video." Disable VP9 codec Cairo seekbar is disabled. "Cairo seekbar is enabled. @@ -308,6 +315,7 @@ The Expand video description option may not work if the entered string does not Video descriptions are expanded automatically. Expand video descriptions Do you wish to proceed? + Reset to default values. Restart to load the layout normally Refresh and restart Failed to export settings. @@ -581,6 +589,9 @@ Words with uppercase letters in the middle must be entered with the casing (ie: Movies shelves are shown. Movies shelves are hidden. Hide movies shelves + Navigation bar is shown. + Navigation bar is hidden. + Hide navigation bar Create button is shown. Create button is hidden. Hide Create button @@ -742,6 +753,12 @@ Words with uppercase letters in the middle must be entered with the casing (ie: More videos section in the quick actions container and the related video overlay are shown. More videos section in the quick actions container and the related video overlay are hidden. Hide related video overlay + Related videos are shown. + Related videos are hidden. + Hide related videos + "This setting limits the maximum number of layouts that can be loaded on the player screen. + +If the layout of the player screen changes due to server-side changes, unintended layouts may be hidden on the player screen." Remix button is shown. Remix button is hidden. Hide Remix button @@ -806,6 +823,9 @@ Captions" Video link label is shown. Video link label is hidden. Hide full video link label + Green screen button is shown. + Green screen button is hidden. + Hide Green screen button Info panels are shown. Info panels are hidden. Hide info panels @@ -839,9 +859,9 @@ Captions" Remix button is shown. Remix button is hidden. Hide Remix button - Save sound to playlist button is shown. - Save sound to playlist button is hidden. - Hide save sound to playlist button + Save music button is shown. + Save music button is hidden. + Hide Save music button Search suggestions button is shown. Search suggestions button is hidden. Hide search suggestions button @@ -876,6 +896,9 @@ Side effect: Official headers in search results will be hidden." Metadata label is shown. Metadata label is hidden. Hide sound metadata label + Stickers are shown. + Stickers are hidden. + Hide stickers Subscribe button is shown. Subscribe button is hidden. Hide Subscribe button @@ -951,15 +974,13 @@ Settings → Autoplay → Autoplay next video" Transcript section is shown. Transcript section is hidden. Hide Transcript section + "Hide videos with UPCOMING label. + +Note: Enabling this also hides the Notify me button." + Hide UPCOMING video Video ads are shown. Video ads are hidden. Hide video ads - Videos with durations longer than this number will be hidden. - Longer than duration - Videos with durations shorter than this number will be hidden. - Shorter than duration - Hide videos with shorter than or longer than duration.\n\nKnown issue: It will not hide videos in the player related videos, instead it will hide the timestamp. - Hide videos based on duration "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. Limitations: @@ -1003,6 +1024,9 @@ Limitations: MMT MMT Blue MMT Green + MMT Orange + MMT Pink + MMT Turquoise MMT Yellow Revancify Blue Revancify Red @@ -1034,7 +1058,7 @@ Limitations: Subtexts are shown. Subtexts are hidden. Hide subtexts - Miniplayer overlay opacity must be between 0-100. Reset to default values. + Miniplayer overlay opacity must be between 0-100. Opacity value between 0-100, where 0 is transparent. Overlay opacity Original @@ -1075,13 +1099,18 @@ Tap and hold to open whitelist setting dialog. Native video download button opens the native in-app downloader. Native video download button opens your external downloader. Override video download button + YouTube Music is required to override button action. Tap here to download YouTube Music. + Prerequisite + YouTube Music button opens the native app. + YouTube Music button opens the RVX Music. + Override YouTube Music button Excluded Included Normal Action buttons Additional settings Animation / Feedback - Duration filter + Download button Experimental Flags Image region restrictions Import / Export as file @@ -1093,6 +1122,7 @@ Tap and hold to open whitelist setting dialog. Quick actions Recommended video Shorts shelves + Suggested actions Tool used View count filter Hide or show elements in account menu and You tab. @@ -1123,13 +1153,15 @@ Tap and hold to open whitelist setting dialog. General Disable or enable haptic feedback. Haptic feedback + Overrides the click action of in-app buttons. + Hook buttons Import or export settings. Import / Export settings Change the style of the in app minimized player. Miniplayer Miscellaneous - Hide or show navigation bar section components. - Navigation buttons + Hide or show navigation bar section components. + Navigation bar Information about applied patches. Patch information Hide or show buttons in the video player. @@ -1158,13 +1190,14 @@ Tap and hold to open whitelist setting dialog. Video Change settings related with watch history. Watch history - Quick actions top margin must be between 0-32. Reset to default values. + Quick actions top margin must be between 0-32. Configure the spacing from the seekbar to the quick action container, between 0-32. Quick actions top margin "Forcefully rejects the software AV1 codec response. A different codec will be applied after about 20 seconds of buffering." Reject software AV1 codec response Fallback process causes about 20 seconds of buffering. + Offset Playback speed changes only apply to the current video. Playback speed changes apply to all videos. Remember playback speed changes @@ -1429,9 +1462,12 @@ Limitation: Dislikes may not appear if the user is not logged in or in incognito Heart (Tint) Hidden Double-tap animation - Meta panel bottom margin must be between 0-64. Reset to default values. + Meta panel bottom margin must be between 0-64. Configure the spacing from the seekbar to the meta panel, between 0-64. Meta panel bottom margin + Height percentage must be between 0-100 (%). + Configure the height percentage of the empty space left when the navigation bar is hidden, between 0 and 100 (%). + Height percentage of empty space Press and hold the timestamp to change the Shorts repeat status. Timestamp long press action "Shows the video title section in fullscreen. @@ -1452,7 +1488,7 @@ Info: Show a toast when skipping Turning on this setting may cause video playback issues. Skipped preloaded buffer. - Speed overlay value must be between 0-8.0. Reset to default values. + Speed overlay value must be between 0-8.0. Speed overlay value between 0-8.0. Speed overlay value "Spoofing the client version to the old version. @@ -1486,10 +1522,14 @@ High quality may be unlocked on some videos that require high device dimensions, "Enabling this might improve battery life and fix playback stuttering. AVC (H.264) has a maximum resolution of 1080p, and video playback will use more internet data than VP9 or AV1." - • Audio track menu is missing. - • Audio track menu is missing. + "• Audio track menu is missing. +• Stable volume is not available." + "• Audio track menu is missing. +• Stable volume is not available." "• Movies or paid videos may not play. -• Livestreams start from the beginning." +• Livestreams start from the beginning. +• Videos may end 1 second early. +• No opus audio codec." Spoofing side effects • Video may not play. Client used to fetch streaming data is hidden in Stats for nerds. @@ -1512,7 +1552,7 @@ AVC (H.264) has a maximum resolution of 1080p, and video playback will use more Swipe magnitude threshold The visibility of swipe overlay background. Swipe background visibility - Swipeable area size cannot be more than 50. Reset to default value. + Swipeable area size cannot be more than 50. Percentage of swipeable screen area.\n\nNote: This will also change the size of the screen area for the double-tap-to-seek gesture. Swipe overlay screen size The text size for swipe overlay. @@ -1535,6 +1575,10 @@ Also, ads will no longer be blocked in Shorts. If this setting do not take effect, try switching to Incognito mode." Stock + RVX Music + %s is not installed. Please install it. + Package name of installed RVX Music. + RVX Music package name • Watch history is blocked. "• Follows the watch history settings of Google account. • Watch history may not work due to DNS or VPN." diff --git a/src/main/resources/youtube/settings/xml/revanced_prefs.xml b/src/main/resources/youtube/settings/xml/revanced_prefs.xml index 18c494d9d..e2d1fc208 100644 --- a/src/main/resources/youtube/settings/xml/revanced_prefs.xml +++ b/src/main/resources/youtube/settings/xml/revanced_prefs.xml @@ -16,6 +16,27 @@ SETTINGS: HIDE_LAYOUT_COMPONENTS --> + + + + + + + + @@ -34,7 +55,7 @@ SETTINGS: MINIPLAYER_TYPE_MODERN --> + + + SETTINGS: HIDE_NAVIGATION_COMPONENTS --> - + + SETTINGS: CHANGE_START_PAGE --> @@ -114,12 +138,6 @@ SETTINGS: LAYOUT_SWITCH --> - - @@ -608,11 +632,58 @@ + + + + + + + + + + + PREFERENCE_SCREEN: RETURN_YOUTUBE_DISLIKE --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PREFERENCE_SCREEN: SPONSOR_BLOCK --> @@ -760,6 +831,7 @@ + diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_remix_filled_white_24.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_remix_filled_white_24.webp new file mode 100644 index 000000000..a14d4adc6 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_remix_filled_white_24.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_remix_filled_white_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_remix_filled_white_shadowed.webp new file mode 100644 index 000000000..a14d4adc6 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_remix_filled_white_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_comment_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_comment_shadowed.webp new file mode 100644 index 000000000..7f272fe24 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_comment_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_dislike_off_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_dislike_off_shadowed.webp new file mode 100644 index 000000000..6ee3b5eb5 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_dislike_off_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_dislike_on_32c.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_dislike_on_32c.webp new file mode 100644 index 000000000..3aaf383d1 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_dislike_on_32c.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_dislike_on_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_dislike_on_shadowed.webp new file mode 100644 index 000000000..3aaf383d1 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_dislike_on_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_like_off_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_like_off_shadowed.webp new file mode 100644 index 000000000..8025cd0ab Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_like_off_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_like_on_32c.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_like_on_32c.webp new file mode 100644 index 000000000..4c889a255 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_like_on_32c.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_like_on_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_like_on_shadowed.webp new file mode 100644 index 000000000..4c889a255 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_like_on_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_share_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_share_shadowed.webp new file mode 100644 index 000000000..59853c62f Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-hdpi/ic_right_share_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_remix_filled_white_24.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_remix_filled_white_24.webp new file mode 100644 index 000000000..970ddeaeb Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_remix_filled_white_24.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_remix_filled_white_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_remix_filled_white_shadowed.webp new file mode 100644 index 000000000..970ddeaeb Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_remix_filled_white_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_comment_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_comment_shadowed.webp new file mode 100644 index 000000000..40b471ab4 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_comment_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_dislike_off_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_dislike_off_shadowed.webp new file mode 100644 index 000000000..5a839a028 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_dislike_off_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_dislike_on_32c.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_dislike_on_32c.webp new file mode 100644 index 000000000..93c5fb715 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_dislike_on_32c.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_dislike_on_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_dislike_on_shadowed.webp new file mode 100644 index 000000000..93c5fb715 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_dislike_on_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_like_off_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_like_off_shadowed.webp new file mode 100644 index 000000000..fcba929e5 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_like_off_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_like_on_32c.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_like_on_32c.webp new file mode 100644 index 000000000..a2149ca24 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_like_on_32c.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_like_on_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_like_on_shadowed.webp new file mode 100644 index 000000000..a2149ca24 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_like_on_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_share_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_share_shadowed.webp new file mode 100644 index 000000000..a75465144 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-mdpi/ic_right_share_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_remix_filled_white_24.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_remix_filled_white_24.webp new file mode 100644 index 000000000..335520b11 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_remix_filled_white_24.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_remix_filled_white_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_remix_filled_white_shadowed.webp new file mode 100644 index 000000000..335520b11 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_remix_filled_white_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_comment_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_comment_shadowed.webp new file mode 100644 index 000000000..5fe1f5d51 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_comment_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_dislike_off_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_dislike_off_shadowed.webp new file mode 100644 index 000000000..83b9c1da8 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_dislike_off_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_dislike_on_32c.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_dislike_on_32c.webp new file mode 100644 index 000000000..6c4a46102 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_dislike_on_32c.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_dislike_on_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_dislike_on_shadowed.webp new file mode 100644 index 000000000..6c4a46102 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_dislike_on_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_like_off_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_like_off_shadowed.webp new file mode 100644 index 000000000..e59653ed1 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_like_off_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_like_on_32c.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_like_on_32c.webp new file mode 100644 index 000000000..3db533ee9 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_like_on_32c.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_like_on_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_like_on_shadowed.webp new file mode 100644 index 000000000..3db533ee9 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_like_on_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_share_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_share_shadowed.webp new file mode 100644 index 000000000..800cce93e Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xhdpi/ic_right_share_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_remix_filled_white_24.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_remix_filled_white_24.webp new file mode 100644 index 000000000..c2ee4badf Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_remix_filled_white_24.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_remix_filled_white_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_remix_filled_white_shadowed.webp new file mode 100644 index 000000000..c2ee4badf Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_remix_filled_white_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_comment_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_comment_shadowed.webp new file mode 100644 index 000000000..b58b8c935 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_comment_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_dislike_off_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_dislike_off_shadowed.webp new file mode 100644 index 000000000..c2f8f3fed Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_dislike_off_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_dislike_on_32c.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_dislike_on_32c.webp new file mode 100644 index 000000000..86d7f8b2f Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_dislike_on_32c.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_dislike_on_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_dislike_on_shadowed.webp new file mode 100644 index 000000000..86d7f8b2f Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_dislike_on_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_like_off_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_like_off_shadowed.webp new file mode 100644 index 000000000..52145c052 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_like_off_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_like_on_32c.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_like_on_32c.webp new file mode 100644 index 000000000..d56e5f992 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_like_on_32c.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_like_on_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_like_on_shadowed.webp new file mode 100644 index 000000000..d56e5f992 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_like_on_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_share_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_share_shadowed.webp new file mode 100644 index 000000000..cb1dfdd56 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxhdpi/ic_right_share_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_remix_filled_white_24.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_remix_filled_white_24.webp new file mode 100644 index 000000000..09d18ebd5 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_remix_filled_white_24.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_remix_filled_white_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_remix_filled_white_shadowed.webp new file mode 100644 index 000000000..09d18ebd5 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_remix_filled_white_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_comment_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_comment_shadowed.webp new file mode 100644 index 000000000..b44137aad Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_comment_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_dislike_off_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_dislike_off_shadowed.webp new file mode 100644 index 000000000..2a48b95d3 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_dislike_off_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_dislike_on_32c.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_dislike_on_32c.webp new file mode 100644 index 000000000..56d8f864b Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_dislike_on_32c.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_dislike_on_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_dislike_on_shadowed.webp new file mode 100644 index 000000000..56d8f864b Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_dislike_on_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_like_off_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_like_off_shadowed.webp new file mode 100644 index 000000000..a5859482f Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_like_off_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_like_on_32c.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_like_on_32c.webp new file mode 100644 index 000000000..c2b56b098 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_like_on_32c.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_like_on_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_like_on_shadowed.webp new file mode 100644 index 000000000..c2b56b098 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_like_on_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_share_shadowed.webp b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_share_shadowed.webp new file mode 100644 index 000000000..5a9476c23 Binary files /dev/null and b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable-xxxhdpi/ic_right_share_shadowed.webp differ diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable/ic_right_comment_32c.xml b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable/ic_right_comment_32c.xml new file mode 100644 index 000000000..8919e0a6f --- /dev/null +++ b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable/ic_right_comment_32c.xml @@ -0,0 +1,404 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable/ic_right_dislike_off_32c.xml b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable/ic_right_dislike_off_32c.xml new file mode 100644 index 000000000..54f0a62ce --- /dev/null +++ b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable/ic_right_dislike_off_32c.xml @@ -0,0 +1,588 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable/ic_right_like_off_32c.xml b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable/ic_right_like_off_32c.xml new file mode 100644 index 000000000..abbd8382d --- /dev/null +++ b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable/ic_right_like_off_32c.xml @@ -0,0 +1,600 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable/ic_right_share_32c.xml b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable/ic_right_share_32c.xml new file mode 100644 index 000000000..12f19f0ef --- /dev/null +++ b/src/main/resources/youtube/shorts/actionbuttons/cairo/drawable/ic_right_share_32c.xml @@ -0,0 +1,684 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/youtube/translations/ar/missing_strings.xml b/src/main/resources/youtube/translations/ar/missing_strings.xml index 26b7e32ef..43ef1657d 100644 --- a/src/main/resources/youtube/translations/ar/missing_strings.xml +++ b/src/main/resources/youtube/translations/ar/missing_strings.xml @@ -2,33 +2,21 @@ Don\'t show again Courses / Learning - Playables Package name of your installed external downloader app, such as NewPipe or YTDLnis, on long press. Long press video downloader package name Displays the optimization dialog for GMSCore at each application startup. Show optimization dialog for GMSCore - "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. - -Limitations: -• Shorts cannot be hidden. -• Videos with 0 views are not filtered." - About view count filtering - Videos in home feed are not filtered. - Videos in home feed are filtered. - Hide home videos by views - Search results are not filtered. - Search results are filtered. - Hide search results by views - Videos in subscriptions feed are not filtered. - Videos in subscriptions feed are filtered. - Hide subscription videos by views MMT Blue MMT Green + MMT Orange + MMT Pink + MMT Turquoise MMT Yellow Revancify Yellow Vanced Black Vanced Light Xisr Yellow + Offset Adjust: Mark Start and End Time for segment Verify the Segment Edit the Segment diff --git a/src/main/resources/youtube/translations/ar/strings.xml b/src/main/resources/youtube/translations/ar/strings.xml index fb7d3b3bc..95c66b772 100644 --- a/src/main/resources/youtube/translations/ar/strings.xml +++ b/src/main/resources/youtube/translations/ar/strings.xml @@ -22,6 +22,7 @@ انقر هنا لمعرفة المزيد عن DeArrow." DeArrow + URL الخاص بـ DeArrow API غير صالح. The URL of The DeArrow Thumbnail Cache Endpoint. DeArrow API Endpoint لا يتم عرض ملاحظة إذا كان DeArrow غير متوفر. @@ -89,8 +90,12 @@ الاشتراكات المحتوى الرائج المشاهدة لاحقًا - صفحة البداية غير صالحة، تتم إعادة التعيين إلى الوضع الافتراضي. تغيير صفحة البداية + تتغير صفحة البدء مرة واحدة فقط. + "تتغير صفحة البدء دائمًا. + +التقييد: قد لا يعمل زر الرجوع الذي على شريط الأدوات." + تغيير نوع صفحة البداية تم تمكين العلامة العامة. تم تمكين علامة Premium. تغيير علامة YouTube @@ -103,11 +108,11 @@ يتم استخدام القائمة المنبثقة بالمظهر القديم. يتم استخدام مربع الحوار المخصص. نوع قائمة سرعة التشغيل المخصصة - يجب أن تكون السرعات المخصصة أقل من %sx. باستخدام القيم الافتراضية. - سرعات التشغيل المخصصة غير صالحة. باستخدام القيم الافتراضية. + يجب أن تكون السرعات المخصصة أقل من %sx. + سرعات التشغيل المخصصة غير صالحة. إضافة أو تغيير سرعات التشغيل المتاحة. تعديل سرعة التشغيل المخصصة - يجب أن تكون شفافية واجهة المشغل بين 0-100. إعادة التعيين إلى القيم الافتراضية. + يجب أن تكون شفافية واجهة المشغل بين 0-100. قيمة التعتيم بين 0-100، حيث 0 شفافة. شفافية واجهة المشغل المخصصة اكتب رمز اللون للون شريط تقدم الفيديو. @@ -187,6 +192,9 @@ عدد المشاهدات والإعجابات متحركة. عدد المشاهدات والإعجابات غير متحركة. تعطيل عدد المشاهدات والإعجابات في الوقت الفعلي + تم تمكين الرسوم المتحركة الفوّارة فوق زر أعجبني. + تم تعطيل الرسوم المتحركة الفوّارة فوق زر أعجبني. + تعطيل الرسوم المتحركة لزر أعجبني "تعطيل '2x>>' أثناء الضغط باستمرار. ملحوظة: @@ -206,7 +214,7 @@ • الحد الأقصى للدقة هو 1080P. • سيستهلك تشغيل الفيديو بيانات إنترنت أكثر من VP9. -• للحصول على تشغيل HDR، لا يزال فيديو HDR يستخدم برنامج ترميز VP9." +• لا يزال برنامج ترميز VP9 مستخدمًا لفيديو HDR." تعطيل ترميز VP9 تم تعطيل شريط تقدم Cairo. "تم تمكين شريط تقدم Cairo. @@ -305,6 +313,7 @@ يتم توسيع أوصاف الفيديو تلقائيًا. توسيع وصف الفيديو هل ترغب في المتابعة؟ + إعادة التعيين إلى القيم الافتراضية. إعادة التشغيل لتحميل التخطيط بشكل طبيعي تحديث وإعادة تشغيل فشل تصدير الإعدادات. @@ -574,6 +583,9 @@ يتم عرض رفوف الأفلام. تم إخفاء رفوف الأفلام. إخفاء رفوف الأفلام + يتم عرض شريط التنقل. + تم إخفاء شريط التنقل. + إخفاء شريط التنقل يتم عرض زر الإنشاء. تم إخفاء زر الإنشاء. إخفاء زر الإنشاء @@ -735,6 +747,12 @@ يتم عرض قسم المزيد من مقاطع الفيديو في حاوية الإجراءات السريعة وواجهة الفيديو ذي الصلة. تم إخفاء قسم المزيد من مقاطع الفيديو في حاوية الإجراءات السريعة وواجهة الفيديو ذي الصلة. إخفاء تراكب الفيديو ذي الصلة + يتم عرض الفيديوهات ذات الصلة. + تم إخفاء الفيديوهات ذات الصلة. + إخفاء الفيديوهات ذات الصلة + "يحد هذا الإعداد من الحد الأقصى لعدد التخطيطات التي يمكن تحميلها على شاشة المشغل. + +إذا تغير تخطيط شاشة المشغل بسبب تغييرات على جانب الخادم، فقد يتم إخفاء التخطيطات غير المقصودة على شاشة المشغل." يتم عرض زر ريمكس. تم إخفاء زر ريمكس. إخفاء زر ريمكس @@ -799,6 +817,9 @@ يتم عرض تسمية رابط الفيديو. تم إخفاء تسمية رابط الفيديو. إخفاء تسمية رابط الفيديو الكامل + يتم عرض زر الشاشة الخضراء. + تم إخفاء زر الشاشة الخضراء. + إخفاء زر الشاشة الأخضر يتم عرض لوحات المعلومات. تم إخفاء لوحات المعلومات. إخفاء لوحات المعلومات @@ -832,9 +853,9 @@ يتم عرض زر ريمكس. تم إخفاء زر ريمكس. إخفاء زر ريمكس - يتم عرض زر حفظ الصوت في قائمة التشغيل. - تم إخفاء زر حفظ الصوت في قائمة التشغيل. - إخفاء زر حفظ الصوت إلى قائمة التشغيل + يتم عرض زر حفظ الموسيقى. + تم إخفاء زر حفظ الموسيقى. + إخفاء زر حفظ الموسيقى يتم عرض زر اقتراحات البحث. تم إخفاء زر اقتراحات البحث. إخفاء زر اقتراحات البحث @@ -869,6 +890,9 @@ يتم عرض تسمية البيانات الوصفية. تم إخفاء تسمية البيانات الوصفية. إخفاء تسمية بيانات التعريف الصوتية + يتم عرض الملصقات. + تم إخفاء الملصقات. + إخفاء الملصقات يتم عرض زر اشتراك. تم إخفاء زر اشتراك. إخفاء زر اشتراك @@ -944,15 +968,29 @@ يتم عرض قسم النص. تم إخفاء قسم النص. إخفاء قسم النص + "إخفاء الفيديوهات التي تحمل علامة \"قادم\". + +ملاحظة: يؤدي تمكين هذا أيضًا إلى إخفاء زر \"تنبيهي\"." + إخفاء الفيديو القادم يتم عرض إعلانات الفيديو. تم إخفاء إعلانات الفيديو. إخفاء إعلانات الفيديو - سيتم إخفاء الفيديوهات التي تزيد مدتها عن هذا الرقم. - الأطول من المـدة - سيتم إخفاء الفيديوهات التي تقل مدتها عن هذا الرقم. - الأقصر من المـدة - إخفاء مقاطع الفيديو التي تقل مدتها عن المدة أو أطول منها.\n\nمشكلة معروفة: لن يؤدي ذلك إلى إخفاء مقاطع الفيديو في مقاطع الفيديو ذات الصلة بالمشغل، بل سيخفي الطابع الزمني بدلاً من ذلك. - إخفاء الفيديوهات بناءً على المـدة + "الصفحة الرئيسية / الاشتراكات / تتم تصفية نتائج البحث لإخفاء مقاطع الفيديو التي حصلت على عدد مشاهدات أقل أو أكبر من عدد محدد. + +القيود: + +• لا يمكن إخفاء فيديوهات Shorts. +• لا تتم تصفية الفيديوهات التي حصلت على 0 مشاهدة." + حول تصفية عدد المشاهدات + لا يتم تصفية الفيديوهات في موجز الصفحة الرئيسية. + يتم تصفية الفيديوهات في موجز الصفحة الرئيسية. + إخفاء فيديوهات الصفحة الرئيسية حسب عدد المشاهدات + لا يتم تصفية نتائج البحث. + يتم تصفية نتائج البحث. + إخفاء نتائج البحث حسب عدد المشاهدات + لا يتم تصفية الفيديوهات في موجز الاشتراكات. + يتم تصفية الفيديوهات في موجز الاشتراكات. + إخفاء فيديوهات الاشتراكات حسب عدد المشاهدات إخفاء الفيديوهات الموصى بها التي حصلت على عدد أقل من عدد معين من المشاهدات.\n\nمشكلة معروفة: لا يتم تصفية الفيديوهات التي حصلت على 0 مشاهدة. إخفاء الفيديوهات الموصى بها عن طريق المشاهدات سيتم إخفاء الفيديوهات التي تزيد مشاهداتها عن هذا الرقم. @@ -1005,7 +1043,7 @@ يتم عرض النصوص الفرعية. تم إخفاء النصوص الفرعية. إخفاء النصوص الفرعية - يجب أن تكون نسبة شفافية واجهة المشغل المصغر بين 0-100. إعادة التعيين إلى القيم الافتراضية. + يجب أن تكون نسبة شفافية واجهة المشغل المصغر بين 0-100. قيمة الشفافية بين 0-100، حيث يكون 0 شفاف. شفافية الواجهة الأصلي @@ -1046,13 +1084,18 @@ يفتح زر تنزيل الفيديو أداة التنزيل الأصلية داخل التطبيق. يفتح زر تنزيل الفيديو الأصلي أداة التنزيل الخارجية. تجاوز زر تنزيل الفيديو + موسيقى YouTube مطلوبًا لتجاوز إجراء الزر. انقر هنا لتنزيل موسيقى YouTube. + متطلب أساسي + زر موسيقى YouTube يفتح التطبيق الأصلي. + زر موسيقى YouTube يفتح موسيقى RVX. + تجاوز زر موسيقى YouTube مستبعد مضمن عادي أزرار الإجراء إعدادات إضافية تأثير الحركة / رد الفعل - فلترة المـدة + زر التنزيل تعديلات تجريبية قيود منطقة الصورة استيراد / تصدير كملف @@ -1064,6 +1107,7 @@ الإجراءات السريعة الفيديو الموصى به رفوف Shorts + الإجراءات المقترحة الأداة المستخدمة تصفية عدد المشاهدات إخفاء أو عرض العناصر في قائمة الحساب وعلامة التبويب أنت. @@ -1094,13 +1138,15 @@ عام تعطيل أو تمكين الاهتزاز. ردود الفعل اللمسية + يتجاوز إجراء النقر على الأزرار الموجودة داخل التطبيق. + أزرار الإرتباط إستيراد أو تصدير الإعدادات. استيراد / تصدير الإعدادات تغيير نمط المشغل المصغر داخل التطبيق. المشغل المصغر خيارات متنوعة - إخفاء أو عرض مكونات قسم شريط التنقل. - أزرار التنقل + إخفاء أو عرض مكونات قسم شريط التنقل. + شريط التنقل معلومات عن التعديلات المطبقة. معلومات التعديل إخفاء أو عرض الأزرار في مشغل الفيديو. @@ -1129,7 +1175,7 @@ الفيديو تغيير الإعدادات المتعلقة بسجل المشاهدة. سجل المشاهدة - يجب أن يكون الهامش العلوي للإجراءات السريعة بين 0-32. إعادة التعيين إلى القيم الافتراضية. + يجب أن يكون الهامش العلوي للإجراءات السريعة بين 0-32. تكوين التباعد من شريط التقدم إلى حاوية الإجراء السريع، بين 0-32. هامش إجراءات سريعة أعلى "يرفض قسرًا استجابة برنامج ترميز AV1. @@ -1247,7 +1293,7 @@ تظهر الملاحظة عند تخطي مقطع تلقائيًا. اضغط هنا لمشاهدة مثال. عرض مدة الفيديو بدون المقاطع يتم عرض مدة الفيديو كاملةً. - يعرض طول الفيديو ناقصًا منه طول المقطع المدمج بين قوسين بجوار طول الفيديو الكامل. + يعرض مدة الفيديو ناقصًا منها مدة المقطع المدمج بين قوسين بجوار مدة الفيديو الكامل. معرف المستخدم User ID الفريد الخاص بك يجب أن يكون معرف المستخدم الخاص 30 حرفًا على الأقل. يجب أن يبقى هذا خاصًا. انه مثل كلمة المرور ولا ينبغي مشاركته مع أي شخص. إذا كان شخص ما يملك هذا، فيمكنه انتحال شخصيتك. @@ -1393,9 +1439,12 @@ قلب(ملون) مخفي تأثير الحركة عند النقر المزدوج - يجب أن يكون الهامش السفلي للوحة التعريف بين 0-64. إعادة التعيين إلى القيم الافتراضية. + يجب أن يكون الهامش السفلي للوحة التعريف بين 0-64. تكوين التباعد من شريط التقدم إلى لوحة التعريف، بين 0-64. الهامش السفلي للوحة التعريف + يجب أن تكون نسبة الارتفاع بين 0-100 (%). + يقوم بتكوين نسبة ارتفاع المساحة الفارغة المتبقية عند إخفاء شريط التنقل، بين 0 و100 (%). + نسبة ارتفاع المساحة الفارغة اضغط مع الاستمرار على الطابع الزمني لتغيير حالة تكرار فيديوهات Shorts. إجراء الضغط المطول على الوقت "يعرض قسم عنوان الفيديو في وضع ملء الشاشة. @@ -1415,7 +1464,7 @@ عرض ملاحظة عند التخطي تشغيل هذا الإعداد قد يسبب مشاكل في تشغيل الفيديو. تم تخطي التخزين المؤقت الذي تم تحميله مسبقًا. - يجب أن تكون قيمة تراكب السرعة بين 0-8.0. إعادة التعيين إلى القيم الافتراضية. + يجب أن تكون قيمة تراكب السرعة بين 0-8.0. قيمة تراكب السرعة بين 0-8.0. قيمة تراكب السرعة "خداع نسخة التطبيق الحالية إلى النسخة القديمة. @@ -1449,10 +1498,14 @@ "قد يؤدي تمكين هذا إلى تحسين عمر البطارية وإصلاح مشكلة تقطيع التشغيل. يتمتع تنسيق AVC (H.264) بدقة قصوى تبلغ 1080P، وسيستخدم تشغيل الفيديو بيانات إنترنت اكثر من VP9 أو AV1." - • قائمة المقطع الصوتي مفقودة. - • قائمة المقطع الصوتي مفقودة. + "• قائمة المقطع الصوتي مفقودة. +• مستوى الصوت الثابت غير متوفر." + "• قائمة المقطع الصوتي مفقودة. +• مستوى الصوت الثابت غير متوفر." "• قد لا يتم تشغيل الأفلام أو الفيديوهات المدفوعة. -• يبدأ البث المباشر من البداية." +• يبدأ البث المباشر من البداية. +• قد تنتهي الفيديوهات قبل النهاية بثانية واحدة. +• لا يوجد ترميز الصوت Opus." التأثيرات الجانبية للتزييف • قد لا يتم تشغيل الفيديو. تم إخفاء العميل المستخدم لجلب بيانات البث في إحصاءات تقنية. @@ -1479,7 +1532,7 @@ الافتراضي:127 شفافية خلفية واجهة إيماءة التمرير - لا يمكن أن يزيد حجم المنطقة القابلة للتمرير السريع عن 50. إعادة التعيين إلى القيمة الافتراضية. + لا يمكن أن يزيد حجم المنطقة القابلة للتمرير السريع عن 50. النسبة المئوية لمساحة الشاشة القابلة للتمرير السريع.\n\nملاحظة: سيؤدي هذا أيضًا إلى تغيير حجم مساحة الشاشة لإيماءة النقر المزدوج للتقديم أو التأخير. حجم واجهة إيماءة التمرير حجم النص على واجهة التمرير. @@ -1506,6 +1559,10 @@ إذا لم يتم تفعيل هذا الإعداد، فحاول التبديل إلى وضع التصفح المتخفي." الإفتراضي + موسيقى RVX + %s لم يتم تثبيته. الرجاء تثبيته. + اسم الحزمة لموسيقى RVX المثبتة. + اسم حزمة موسيقى RVX • سجل المشاهدة محظور. "• يتبع إعدادات سجل المشاهدة لحساب Google. • قد لا يعمل سجل المشاهدة بسبب DNS أو VPN." diff --git a/src/main/resources/youtube/translations/bg-rBG/missing_strings.xml b/src/main/resources/youtube/translations/bg-rBG/missing_strings.xml index 32def3c27..2423140b7 100644 --- a/src/main/resources/youtube/translations/bg-rBG/missing_strings.xml +++ b/src/main/resources/youtube/translations/bg-rBG/missing_strings.xml @@ -4,7 +4,6 @@ The domain to fetch images from.\nNote: Only enter the domain name, i.e., without the \"https\:\/\/\" prefix. Alternative domain Courses / Learning - Playables Package name of your installed external downloader app, such as NewPipe or YTDLnis, on long press. Long press video downloader package name Displays the optimization dialog for GMSCore at each application startup. @@ -12,23 +11,11 @@ Disabled comments button or with label \"0\" is shown. Disabled comments button or with label \"0\" is hidden. Hide disabled comments button - "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. - -Limitations: -• Shorts cannot be hidden. -• Videos with 0 views are not filtered." - About view count filtering - Videos in home feed are not filtered. - Videos in home feed are filtered. - Hide home videos by views - Search results are not filtered. - Search results are filtered. - Hide search results by views - Videos in subscriptions feed are not filtered. - Videos in subscriptions feed are filtered. - Hide subscription videos by views MMT Blue MMT Green + MMT Orange + MMT Pink + MMT Turquoise MMT Yellow Revancify Yellow Vanced Black diff --git a/src/main/resources/youtube/translations/bg-rBG/strings.xml b/src/main/resources/youtube/translations/bg-rBG/strings.xml index 7df3a5aa7..2dacc49ba 100644 --- a/src/main/resources/youtube/translations/bg-rBG/strings.xml +++ b/src/main/resources/youtube/translations/bg-rBG/strings.xml @@ -15,6 +15,7 @@ GmsCore не е инсталиран. Инсталирайте го. "DeArrow предоставя миниатюри на публиката за видеоклипове. Тези миниатюри често са по-подходящи от тези, предоставени от самия YouTube. Ако е активирано, URL адресите на видео ще бъдат изпратени до API сървъра, без да се изпращат други данни. Ако видеоклипът няма миниатюри на DeArrow, ще се покажат или неговите оригинални миниатюри, или заснети кадри. Щракнете, за да научите повече за DeArrow." Относно DeArrow + Невалиден DeArrow API URL. URL адресът на крайната точка за съхранение на миниатюри DeArrow. DeArrow API адрес Не се показва известие, ако DeArrow не е наличен. @@ -80,8 +81,12 @@ Абонаменти Популярни За Гледане по-късно - Невалидна начална страница, нулиране по подразбиране. Промяна на началната страница + Началната страница се променя само веднъж. + "Началната страница винаги се променя. + +Ограничение: Бутонът за връщане назад в лентата с инструменти може да не работи." + Промяна на типа на началната страница Включен стандартен логотип. Включен логотип Premium. Промяна на логото на YouTube @@ -177,6 +182,9 @@ Анимацията на числа в реално време е активирана. Анимацията на числа в реално време е деактивирана. Анимация на числа в реално време + Анимацията на фонтан е активирана над бутона „Харесва ми“. + Анимацията на фонтан е деактивирана над бутона „Харесва ми“. + Деактивиране анимацията на бутона „Харесва ми“ "Деактивирайте „Възпроизвеждане с 2x>> скорост при продължително натискане. Бележки: @@ -292,6 +300,7 @@ Описанието на видеоклипа се отваря автоматично. Автоматично отваряне на видео описание Желаете ли да продължите? + Възстановяване на стандартните стойности. Рестартирайте, за да заредите оформлението нормално Опреснете и рестартирайте Неуспешно експортиране на настройките. @@ -558,6 +567,9 @@ Филмовите рафтове се показват. Филмовите рафтове са скрити. Скриване на филмовите рафтове + Навигационната лента се показва. + Навигационната лента е скрита. + Скриване лентата за навигация Бутона за създаване се показва. Бутонът за създаване е скрит. Бутон Създай клип @@ -722,6 +734,12 @@ Скрит. Скрива раздела с още видеоклипове в бързи действия и свързани видеоклипове. Свързани видеоклипове + Сродните клипове се показват. + Сродните клипове са скрити. + Скриване в сродни видеоклипове + "Тази настройка ограничава максималния брой оформления, които могат да бъдат заредени на екрана на плейъра. + +Ако оформлението на екрана на плейъра се промени поради промени от страна на сървъра, нежеланите оформления може да бъдат скрити на екрана на плейъра." Бутона за ремикс се показва. Бутона за ремикс е скрит. Скриване на бутона за ремикс @@ -783,6 +801,9 @@ Етикетът за видео връзка се показва. Етикетът за видео връзка е скрит. Скриване на етикет за връзка към видеоклипа + Зелен бутон на екрана се показва. + Зелен бутон на екрана е скрит. + Зелен бутон на екрана Информационните панели се показват. Информационните панели са скрити. Скриване на информационните панели @@ -816,9 +837,9 @@ Бутона за ремикс се показва. Бутона за ремикс е скрит. Скриване на бутона за ремикс - Бутонът за Запазване в плейлиста се показва. - Бутонът за Запазване в плейлиста е скрит. - Бутон за запазване на аудиото в плейлиста + Показан е бутонът за запазване на музика. + Бутонът за запазване на музика е скрит. + Скриване на бутона Запазване на музика Бутон „Предложения за търсене“ се показва. Бутон „Предложения за търсене“ е скрит. Бутон „Предложения за търсене“ @@ -853,6 +874,9 @@ Метаданни се показват. Метаданни са скрити. Скриване на музикални метаданни + Стикери са показани. + Стикерите са скрити. + Скриване на стикери Показва се бутонът „Абониране“. Бутонът „Абониране“ е скрит. Скрийте бутона „Абониране“ @@ -928,15 +952,24 @@ Note: Разделът за транскрипция е показан. Разделът за транскрипция е скрит. Скриване на раздела за транскрипция + "Скриване на видеоклипове с етикет ПРЕДСТОЯЩО. + +Забележка: Активирането на това също ще скрие бутона Уведоми ме." + ПРЕДСТОЯЩО видео Видео рекламите се показват. Видео рекламите са скрити. Скриване на видео рекламите - Видеоклиповете с по-голяма продължителност ще бъдат скрити. - Продължителност, по-голяма от посочената - Видеоклиповете с по-малка продължителност ще бъдат скрити. - Ограничение за минимална продължителност - Скрийте видеоклипове, по-кратки или по-дълги от предпочитанията ви.\n\nИзвестен проблем: Не работи с предложени видеоклипове под плейъра, но ще скрие клеймото им за време. - Скриване на видеоклипове въз основа на тяхната продължителност + "Начало / Абонамент / Резултатите от търсенето се филтрират, за да скрият видеоклипове с гледания, по-малки или по-големи от определен брой." + Относно филтрирането на броя показвания + Видеоклиповете в раздела Начало не се филтрират. + Видеоклиповете в раздела Начало се филтрират. + Фильтр за видео в \"Начало\" по гледания + Резултатите от търсенето не се филтрират. + Резултатите от търсенето се филтрират. + Филтриране на резултатите от търсенето + Видеоклиповете в емисията за абонаменти не се филтрират. + Видеоклиповете в емисията за абонаменти се филтрират. + Видеоклипове в раздела Абонаменти по показвания Скрийте видеоклиповете с по-малко или повече гледания от предпочитанията ви.\n\nИзвестен проблем: Видеоклиповете с 0 гледания не са правилно филтрирани. Скриване на видеоклипове въз основа на броя гледания Видеоклиповете с повече гледания от този брой няма да бъдат показани. @@ -1028,13 +1061,18 @@ Note: Бутонът за изтегляне на YouTube отваря собствената програма за изтегляне на приложението. Бутонът за изтегляне от YouTube отваря вашата външна програма за изтегляне. Действие на бутона \"Изтегляне\" за видео + Изисква се YouTube Music, за да замени действието на бутона. Докоснете тук, за да изтеглите YouTube Music. + Изисквания + Бутонът YouTube Music отваря вграденото приложение. + Бутонът YouTube Music отваря RVX Music. + Замяна на бутона YouTube Music Изключване Включване Нормално Бутони за действие Допълнителни настройки Анимация / Обратна връзка - Филтриране по продължителност + Бутон Изтегляне Експериментални настройки Ограничения за областта на изображението Импортиране / Експортиране като файл @@ -1046,6 +1084,7 @@ Note: Бързи действия Препоръчани видеоклипове Shorts рафтове + Предложени действия Ползвани инструменти Филтрирайте по брой гледания Скриване или показване на елементи в менюто на акаунта и раздела Вие. @@ -1076,13 +1115,15 @@ Note: Основни настройки Деактивирайте или активирайте вибрационен отговор за събития. Вибрация при докосване (обратна връзка) + Замяна на действията на бутоните в приложението. + Настройки за действие на бутоните Импортиране / Експортиране на настройките. Импортиране / Експортиране на настройките Променете стила на минимизирания екран за възпроизвеждане. Минимизиран екран за възпроизвеждане Разни - Скриване или показване на елементи от лентата за навигация. - Бутони за навигация + Скриване или показване на елементи от лентата за навигация. + Лента за навигация Информация за приложените корекции. Информация за корекции Скриване или показване на бутони на екрана на видеоплейъра. @@ -1118,6 +1159,7 @@ Note: След приблизително 20 секунди буфериране ще бъде приложен друг кодек." Отхвърлете софтуерния кодек AV1 Буфериране поради софтуерен кодек Av1 (прибл. 20 сек.). + Компенсиране Промените в скоростта на възпроизвеждане се отнасят само за текущия видеоклип. Промените в скоростта на възпроизвеждане се отнасят за всички видеоклипове. Запомнете промените в скоростта на възпроизвеждане @@ -1378,6 +1420,9 @@ Note: Полето в долната част на мета панела трябва да е между 0-64, Нулирайте по подразбиране. Отстъп от лентата за възпроизвеждане към панела „мета“ Диапазон от 0 до 64. Долно поле на \"мета\" панела + Процентът на височината трябва да е между 0-100 (%). + Конфигурира процента на височината на оставащото празно пространство, когато лентата за навигация е скрита, между 0 и 100 (%). + Мярка в проценти на празното пространство Натиснете и задръжте клеймото за време, за да превключите състоянието на повторение на Shorts. Продължително натискане на времето "Показва раздела със заглавието на видеоклипа на цял екран. @@ -1428,8 +1473,8 @@ Note: "Активирането на това може да подобри живота на батерията и да коригира прекъсванията при възпроизвеждане. AVC (H.264) има максимална разделителна способност при 1080p и възпроизвеждането на видео ще използва повече интернет данни от VP9 или AV1." - • Липсва менюто за избор на аудио. - • Липсва менюто за избор на аудио. + "• Липсва менюто за избор на аудио." + "• Липсва менюто за избор на аудио." "• Филми или платени видеоклипове може да не се възпроизвеждат." Ефекти от замяната • Видеото може да не се възпроизведе. @@ -1476,6 +1521,10 @@ AVC (H.264) има максимална разделителна способн Ако деактивирането не влезе в сила, опитайте да превключите към режим „инкогнито“." По подразбиране + RVX Music + %s не е инсталирано. Моля инсталирайте го. + Името на пакета с инсталиран RVX Music. + Име на пакета RVX Music • Хронологията на гледане е блокирана. "• Следва настройките на хронологията на сърфирането в акаунта ви в Google. • Историята на сърфиране може да не работи поради DNS или VPN." diff --git a/src/main/resources/youtube/translations/bn/missing_strings.xml b/src/main/resources/youtube/translations/bn/missing_strings.xml index 50d7e1f33..c8a03773a 100644 --- a/src/main/resources/youtube/translations/bn/missing_strings.xml +++ b/src/main/resources/youtube/translations/bn/missing_strings.xml @@ -1,6 +1,7 @@ Don\'t show again + Invalid DeArrow API URL. Still video captures The domain to fetch images from.\nNote: Only enter the domain name, i.e., without the \"https\:\/\/\" prefix. Alternative domain @@ -16,11 +17,14 @@ Live Movies Music - Playables Sports Watch later - Invalid start page, resetting to default. - Player overlay opacity must be between 0-100. Reset to default values. + Start page changes only once. + "Start page always changes. + +Limitation: Back button on the toolbar may not work." + Change start page type + Player overlay opacity must be between 0-100. Ambient mode is enabled in fullscreen. Ambient mode is disabled in fullscreen. Ambient mode is enabled. @@ -40,12 +44,15 @@ Limitation: This setting may not apply to videos that do not include the 'Listen Like and Dislike buttons will glow when mentioned. Like and Dislike buttons will not glow when mentioned. Disable Like and Dislike button glow + Fountain animation is enabled above the Like button. + Fountain animation is disabled above the Like button. + Disable Like button animation VP9 codec is enabled. "VP9 codec is disabled. • Maximum resolution is 1080p. • Video playback will use more internet data than VP9. -• To get HDR playback, HDR video still uses the VP9 codec." +• VP9 codec is still used for HDR video." Disable VP9 codec Cairo seekbar is disabled. "Cairo seekbar is enabled. @@ -71,6 +78,7 @@ Limitations: Navigation bar is translucent. Enable translucent navigation bar Do you wish to proceed? + Reset to default values. Search %s Package name of your installed external downloader app, such as YTDLnis. Playlist downloader package name @@ -117,6 +125,9 @@ Side effect: Community post images may be blocked in fullscreen." Hide live chat replay button Hide videos with less than 1,000 views from home feeds that have been uploaded from unsubscribed channels. Hide low views video + Navigation bar is shown. + Navigation bar is hidden. + Hide navigation bar Ambient mode menu is shown. Ambient mode menu is hidden. Hide Ambient mode menu @@ -129,12 +140,21 @@ Side effect: Community post images may be blocked in fullscreen." Promotion alert banner is shown. Promotion alert banner is hidden. Hide promotion alert banner + Related videos are shown. + Related videos are hidden. + Hide related videos + "This setting limits the maximum number of layouts that can be loaded on the player screen. + +If the layout of the player screen changes due to server-side changes, unintended layouts may be hidden on the player screen." Disabled comments button or with label \"0\" is shown. Disabled comments button or with label \"0\" is hidden. Hide disabled comments button "Floating buttons like 'Use this sound' are shown in the Shorts channel tab." "Floating buttons like 'Use this sound' are hidden in the Shorts channel tab." Hide floating button + Green screen button is shown. + Green screen button is hidden. + Hide Green screen button Live chat header is shown.\n\nBack button in header will not be hidden. Live chat header is hidden.\n\nBack button in header will not be hidden. Hide live chat header @@ -147,12 +167,18 @@ Side effect: Community post images may be blocked in fullscreen." Button background is shown. Button background is hidden. Hide Play & Pause button background + Save music button is shown. + Save music button is hidden. + Hide Save music button Search suggestions button is shown. Search suggestions button is hidden. Hide search suggestions button Shopping button is shown. Shopping button is hidden. Hide Shopping button + Stickers are shown. + Stickers are hidden. + Hide stickers Super Thanks button is shown. Super Thanks button is hidden. Hide Super Thanks button @@ -173,6 +199,10 @@ Side effect: Community post images may be blocked in fullscreen." Autoplay can be changed in YouTube settings: Settings → Autoplay → Autoplay next video" + "Hide videos with UPCOMING label. + +Note: Enabling this also hides the Notify me button." + Hide UPCOMING video "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. Limitations: @@ -195,6 +225,9 @@ Limitations: Afn Red MMT Blue MMT Green + MMT Orange + MMT Pink + MMT Turquoise MMT Yellow Revancify Yellow Vanced Black @@ -219,7 +252,7 @@ Limitations: Subtexts are shown. Subtexts are hidden. Hide subtexts - Miniplayer overlay opacity must be between 0-100. Reset to default values. + Miniplayer overlay opacity must be between 0-100. Opacity value between 0-100, where 0 is transparent. Overlay opacity Original @@ -243,15 +276,27 @@ Tap and hold to open whitelist setting dialog. Native video download button opens the native in-app downloader. Native video download button opens your external downloader. Override video download button + YouTube Music is required to override button action. Tap here to download YouTube Music. + Prerequisite + YouTube Music button opens the native app. + YouTube Music button opens the RVX Music. + Override YouTube Music button Animation / Feedback + Download button Image region restrictions + Suggested actions + Overrides the click action of in-app buttons. + Hook buttons Change the style of the in app minimized player. Miniplayer + Hide or show navigation bar section components. + Navigation bar Spoof the streaming data to prevent playback issues. Spoof streaming data Change settings related with watch history. Watch history - Quick actions top margin must be between 0-32. Reset to default values. + Quick actions top margin must be between 0-32. + Offset A toast will not be shown when changing the default playback speed. A toast will be shown when changing the default playback speed. Show a toast @@ -277,15 +322,21 @@ Tap and hold to open whitelist setting dialog. Heart (Tint) Hidden Double-tap animation - Meta panel bottom margin must be between 0-64. Reset to default values. + Meta panel bottom margin must be between 0-64. Configure the spacing from the seekbar to the meta panel, between 0-64. Meta panel bottom margin + Height percentage must be between 0-100 (%). + Configure the height percentage of the empty space left when the navigation bar is hidden, between 0 and 100 (%). + Height percentage of empty space Press and hold the timestamp to change the Shorts repeat status. Timestamp long press action Turning on this setting may cause video playback issues. - Speed overlay value must be between 0-8.0. Reset to default values. + Speed overlay value must be between 0-8.0. Version not spoofed Version spoofed + 18.33.40 - Restore old Shorts action bar + 18.38.45 - Restore old default video quality behavior + 18.48.39 - Disables views and likes from being updated in real time "App version will be spoofed to an older version of YouTube. This will change the appearance and features of the app, but unknown side effects may occur. @@ -297,10 +348,14 @@ If later turned off, it is recommended to clear the app data to prevent UI bugs. "Enabling this might improve battery life and fix playback stuttering. AVC (H.264) has a maximum resolution of 1080p, and video playback will use more internet data than VP9 or AV1." - • Audio track menu is missing. - • Audio track menu is missing. + "• Audio track menu is missing. +• Stable volume is not available." + "• Audio track menu is missing. +• Stable volume is not available." "• Movies or paid videos may not play. -• Livestreams start from the beginning." +• Livestreams start from the beginning. +• Videos may end 1 second early. +• No opus audio codec." Spoofing side effects • Video may not play. Client used to fetch streaming data is hidden in Stats for nerds. @@ -315,7 +370,7 @@ AVC (H.264) has a maximum resolution of 1080p, and video playback will use more iOS Default client Turning off this setting may cause video playback issues. - Swipeable area size cannot be more than 50. Reset to default value. + Swipeable area size cannot be more than 50. Percentage of swipeable screen area.\n\nNote: This will also change the size of the screen area for the double-tap-to-seek gesture. Swipe overlay screen size Create button is not switched with Notifications button. @@ -327,6 +382,10 @@ Note: Enabling this also forcibly hides video ads." Also, ads will no longer be blocked in Shorts. If this setting do not take effect, try switching to Incognito mode." + RVX Music + %s is not installed. Please install it. + Package name of installed RVX Music. + RVX Music package name • Watch history is blocked. "• Follows the watch history settings of Google account. • Watch history may not work due to DNS or VPN." diff --git a/src/main/resources/youtube/translations/bn/strings.xml b/src/main/resources/youtube/translations/bn/strings.xml index cfe99d49a..493e94fde 100644 --- a/src/main/resources/youtube/translations/bn/strings.xml +++ b/src/main/resources/youtube/translations/bn/strings.xml @@ -691,9 +691,6 @@ Captions" Remix button is shown. Remix button is hidden. Hide remix button - Save sound to playlist is shown. - Save sound to playlist is hidden. - Hide save sound to playlist button Share button is shown. Share button is hidden. Hide share button @@ -780,12 +777,6 @@ Note: Video ads are shown. Video ads are hidden. Hide video ads - Videos with duration longer than this number will be hidden. - Longer than duration - Videos with duration shorter than this number will be hidden. - Shorter than duration - Hide videos with shorter than or longer than duration.\n\nKnown issue: It will not hide videos in the player related videos, instead it will hide the timestamp. - Hide videos based on duration Hide recommended videos with less than a specified number of views. Hide recommended videos by views Videos with views greater than this number will be hidden. @@ -836,7 +827,6 @@ Tap and hold to set playback speed to 1.0x." Normal Action buttons Additional settings - Duration filter Experimental Flags Import / Export as file Import / Export as text @@ -880,8 +870,6 @@ Tap and hold to set playback speed to 1.0x." Import or export settings. Import / Export settings Miscellaneous - Hide or show navigation bar section components. - Navigation buttons Information about applied patches. Patch information Hide or show buttons in videos. @@ -1177,9 +1165,6 @@ Limitation: Video title disappears when clicked." 17.41.37 - Restore old playlist shelf 18.05.40 - Restore old comment input box 18.17.43 - Restore old player flyout panel - 18.33.40 - Restore old shorts action bar - 18.38.45 - Restore old default video quality behavior - "18.48.39 - Disables 'views' and 'likes' from being updated in real time" Spoof app version target Type the spoof app version target. Edit spoof app version diff --git a/src/main/resources/youtube/translations/de-rDE/missing_strings.xml b/src/main/resources/youtube/translations/de-rDE/missing_strings.xml index a3f9550d0..116c3350f 100644 --- a/src/main/resources/youtube/translations/de-rDE/missing_strings.xml +++ b/src/main/resources/youtube/translations/de-rDE/missing_strings.xml @@ -1,11 +1,16 @@ Don\'t show again + Invalid DeArrow API URL. In-app share sheet is used. System share sheet is used. Change share sheet Courses / Learning - Playables + Start page changes only once. + "Start page always changes. + +Limitation: Back button on the toolbar may not work." + Change start page type "Auto switch mix playlists is enabled when autoplay is turned on. Autoplay can be changed in YouTube settings: @@ -18,16 +23,20 @@ Settings → Autoplay → Autoplay next video" Limitation: This setting may not apply to videos that do not include the 'Listen on YouTube Music' banner." Disable playback speed for music + Fountain animation is enabled above the Like button. + Fountain animation is disabled above the Like button. + Disable Like button animation VP9 codec is enabled. "VP9 codec is disabled. • Maximum resolution is 1080p. • Video playback will use more internet data than VP9. -• To get HDR playback, HDR video still uses the VP9 codec." +• VP9 codec is still used for HDR video." Disable VP9 codec Do not save and restore brightness when exiting or entering fullscreen. Save and restore brightness when exiting or entering fullscreen. Enable save and restore brightness + Reset to default values. Package name of your installed external downloader app, such as YTDLnis. Playlist downloader package name Package name of your installed external downloader app, such as NewPipe or YTDLnis, on long press. @@ -47,6 +56,9 @@ Limitation: This setting may not apply to videos that do not include the 'Listen Add quotes to use keyword: %s. Keyword has conflicting declarations: %s. Keyword is too short and requires quotes: %s. + Navigation bar is shown. + Navigation bar is hidden. + Hide navigation bar Ambient mode menu is shown. Ambient mode menu is hidden. Hide Ambient mode menu @@ -56,24 +68,39 @@ Limitation: This setting may not apply to videos that do not include the 'Listen Promotion alert banner is shown. Promotion alert banner is hidden. Hide promotion alert banner + Related videos are shown. + Related videos are hidden. + Hide related videos + "This setting limits the maximum number of layouts that can be loaded on the player screen. + +If the layout of the player screen changes due to server-side changes, unintended layouts may be hidden on the player screen." Disabled comments button or with label \"0\" is shown. Disabled comments button or with label \"0\" is hidden. Hide disabled comments button "Floating buttons like 'Use this sound' are shown in the Shorts channel tab." "Floating buttons like 'Use this sound' are hidden in the Shorts channel tab." Hide floating button + Green screen button is shown. + Green screen button is hidden. + Hide Green screen button Location button is shown. Location button is hidden. Hide location button Paused header is shown. Paused header is hidden. Hide paused header + Save music button is shown. + Save music button is hidden. + Hide Save music button Search suggestions button is shown. Search suggestions button is hidden. Hide search suggestions button Shopping button is shown. Shopping button is hidden. Hide Shopping button + Stickers are shown. + Stickers are hidden. + Hide stickers Trends button is shown. Trends button is hidden. Hide Trends button @@ -83,6 +110,10 @@ Limitation: This setting may not apply to videos that do not include the 'Listen Use this sound button is shown. Use this sound button is hidden. Hide Use this sound button + "Hide videos with UPCOMING label. + +Note: Enabling this also hides the Notify me button." + Hide UPCOMING video "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. Limitations: @@ -100,6 +131,9 @@ Limitations: Hide subscription videos by views MMT Blue MMT Green + MMT Orange + MMT Pink + MMT Turquoise MMT Yellow Revancify Yellow Vanced Black @@ -113,10 +147,22 @@ Limitations: Native video download button opens the native in-app downloader. Native video download button opens your external downloader. Override video download button + YouTube Music is required to override button action. Tap here to download YouTube Music. + Prerequisite + YouTube Music button opens the native app. + YouTube Music button opens the RVX Music. + Override YouTube Music button + Download button + Suggested actions + Overrides the click action of in-app buttons. + Hook buttons + Hide or show navigation bar section components. + Navigation bar Spoof the streaming data to prevent playback issues. Spoof streaming data Change settings related with watch history. Watch history + Offset A toast will not be shown when changing the default playback speed. A toast will be shown when changing the default playback speed. Show a toast @@ -132,6 +178,9 @@ Limitations: Publish Created Segment Rewind by Specified Time (Default: 150ms) Tap here to view your segments. + Height percentage must be between 0-100 (%). + Configure the height percentage of the empty space left when the navigation bar is hidden, between 0 and 100 (%). + Height percentage of empty space Turning on this setting may cause video playback issues. iOS video codec is AVC (H.264), VP9, or AV1. iOS video codec is AVC (H.264). @@ -139,10 +188,14 @@ Limitations: "Enabling this might improve battery life and fix playback stuttering. AVC (H.264) has a maximum resolution of 1080p, and video playback will use more internet data than VP9 or AV1." - • Audio track menu is missing. - • Audio track menu is missing. + "• Audio track menu is missing. +• Stable volume is not available." + "• Audio track menu is missing. +• Stable volume is not available." "• Movies or paid videos may not play. -• Livestreams start from the beginning." +• Livestreams start from the beginning. +• Videos may end 1 second early. +• No opus audio codec." Spoofing side effects • Video may not play. Client used to fetch streaming data is hidden in Stats for nerds. @@ -166,6 +219,10 @@ Note: Enabling this also forcibly hides video ads." Also, ads will no longer be blocked in Shorts. If this setting do not take effect, try switching to Incognito mode." + RVX Music + %s is not installed. Please install it. + Package name of installed RVX Music. + RVX Music package name • Watch history is blocked. "• Follows the watch history settings of Google account. • Watch history may not work due to DNS or VPN." diff --git a/src/main/resources/youtube/translations/de-rDE/strings.xml b/src/main/resources/youtube/translations/de-rDE/strings.xml index d200d5ad9..8f07b9d8e 100644 --- a/src/main/resources/youtube/translations/de-rDE/strings.xml +++ b/src/main/resources/youtube/translations/de-rDE/strings.xml @@ -86,7 +86,6 @@ Tippen Sie hier, um mehr über DeArrow zu erfahren." Abonnements Beliebt Später ansehen - Ungültige Startseite, zurücksetzen auf Standard. Startseite ändern Standard Header wird verwendet. Premium Header wird verwendet. @@ -765,9 +764,6 @@ Untertitel" Remix button is shown. Remix button is hidden. Verstecke Remix Button - Save sound to playlist button is shown. - Save sound to playlist button is hidden. - Hide save sound to playlist button Share button is shown. Share button is hidden. Verstecke \"Teilen\" Schaltfläche @@ -865,12 +861,6 @@ Einstellungen → Autoplay → Nächstes Video automatisch abspielen" Videowerbung wird angezeigt. Videowerbung ist versteckt. Verstecke Videowerbung - Videos mit einer Dauer, die länger als diese Zahl ist, werden ausgeblendet. - Länger als Dauer - Videos mit einer Dauer, die länger als diese Zahl ist, werden ausgeblendet. - Kürzer als Dauer - Verstecke Videos mit kürzer oder länger als die Dauer.\n\nBekanntes Problem: Videos werden nicht in den Player-bezogenen Videos ausgeblendet, sondern der Zeitstempel wird versteckt. - Videos je nach Dauer ausblenden Empfohlene Videos mit weniger als einer bestimmten Anzahl von Ansichten ausblenden.\n\nBekanntes Problem: Videos mit 0 Ansichten werden nicht gefiltert. Empfohlene Videos nach Ansichten ausblenden. Videos mit Ansichten, die größer als diese Zahl sind, werden ausgeblendet. @@ -962,7 +952,6 @@ Tippen und halten Sie, um den Einstellungsdialog für die Whitelist anzuzeigen.< Aktionsschaltflächen Additional settings Animation / Feedback - Filterdauer Experimentelle Flags Bildregion-Beschränkungen Als Datei importieren / exportieren @@ -1009,8 +998,6 @@ Tippen und halten Sie, um den Einstellungsdialog für die Whitelist anzuzeigen.< Ändern Sie den Stil des in App minimierten Players. Miniplayer Sonstiges - Komponenten der Navigationsleiste ausblenden oder anzeigen. - Navigationstasten Informationen über angewandte Patches Patch-Informationen Hide or show buttons in the video player. diff --git a/src/main/resources/youtube/translations/el-rGR/missing_strings.xml b/src/main/resources/youtube/translations/el-rGR/missing_strings.xml index 26b7e32ef..a0dadfc3c 100644 --- a/src/main/resources/youtube/translations/el-rGR/missing_strings.xml +++ b/src/main/resources/youtube/translations/el-rGR/missing_strings.xml @@ -2,28 +2,15 @@ Don\'t show again Courses / Learning - Playables Package name of your installed external downloader app, such as NewPipe or YTDLnis, on long press. Long press video downloader package name Displays the optimization dialog for GMSCore at each application startup. Show optimization dialog for GMSCore - "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. - -Limitations: -• Shorts cannot be hidden. -• Videos with 0 views are not filtered." - About view count filtering - Videos in home feed are not filtered. - Videos in home feed are filtered. - Hide home videos by views - Search results are not filtered. - Search results are filtered. - Hide search results by views - Videos in subscriptions feed are not filtered. - Videos in subscriptions feed are filtered. - Hide subscription videos by views MMT Blue MMT Green + MMT Orange + MMT Pink + MMT Turquoise MMT Yellow Revancify Yellow Vanced Black diff --git a/src/main/resources/youtube/translations/el-rGR/strings.xml b/src/main/resources/youtube/translations/el-rGR/strings.xml index 89f8aa1ac..a2ee76beb 100644 --- a/src/main/resources/youtube/translations/el-rGR/strings.xml +++ b/src/main/resources/youtube/translations/el-rGR/strings.xml @@ -20,6 +20,7 @@ Πατήστε για να μάθετε περισσότερα για το DeArrow." Σχετικά με το DeArrow + Μη έγκυρο URL για το DeArrow API. Η διεύθυνση URL του τελικού σημείου αποθήκευσης μικρογραφιών DeArrow. Διεύθυνση API του DeArrow Δεν εμφανίζεται μήνυμα στο κάτω μέρος της οθόνης αν το DeArrow δεν είναι διαθέσιμο. @@ -87,11 +88,15 @@ Εγγραφές Τάσεις Παρακολούθηση αργότερα - Μη έγκυρη αρχική σελίδα, επαναφέρθηκε. Αλλαγή αρχικής σελίδας - Η αρχική επικεφαλίδα είναι ενεργοποιημένη. + Η αρχική σελίδα αλλάζει μόνο μία φορά. + "Η αρχική σελίδα αλλάζει πάντα. + +Περιορισμός: Το κουμπί επιστροφής στη γραμμή εργαλείων ενδέχεται να μη λειτουργεί." + Αλλαγή τύπου αρχικής σελίδας + Η επικεφαλίδα Premium είναι απενεργοποιημένη. Η επικεφαλίδα Premium είναι ενεργοποιημένη. - Αλλαγή επικεφαλίδας YouTube + Επικεφαλίδα Premium Λίστα από συμβολοσειρές στοιχείων που θα φιλτραριστούν, διαχωρισμένες με νέες γραμμές. Επεξεργασία προσαρμοσμένου φίλτρου Το προσαρμοσμένο φίλτρο χρήστη είναι απενεργοποιημένο. @@ -101,16 +106,16 @@ Εμφανίζεται το αναδυόμενο μενού παλιού στυλ. Εμφανίζεται προσαρμοσμένο παράθυρο. Τύπος μενού ταχύτητας αναπαραγωγής - Οι ταχύτητες πρέπει να είναι μικρότερες από %sx, επαναφέρθηκαν. - Μη έγκυρες ταχύτητες αναπαραγωγής, επαναφέρθηκαν. + Οι ταχύτητες πρέπει να είναι μικρότερες από %sx. + Μη έγκυρες ταχύτητες αναπαραγωγής. Προσθέστε ή αλλάξτε τις διαθέσιμες ταχύτητες αναπαραγωγής. Επεξεργασία ταχυτήτων αναπαραγωγής - Η αδιαφάνεια πρέπει να είναι μεταξύ 0-100, επαναφέρθηκε. + Η αδιαφάνεια πρέπει να είναι μεταξύ 0-100. Τιμή αδιαφάνειας μεταξύ 0-100, όπου το 0 είναι διαφανές. Αλλαγή αδιαφάνειας φόντου αναπαραγωγέα Εισάγετε τον κωδικό hex του χρώματος της γραμμής προόδου. Τιμή χρώματος γραμμής προόδου - Για να ανοίγουν οι συνδέσμοι YouTube στο RVX, ενεργοποιήστε το «Άνοιγμα υποστηριζόμενων συνδέσμων» και ενεργοποιήστε τις υποστηριζόμενες διευθύνσεις ιστού. + Για να ανοίγουν οι συνδέσμοι YouTube στο RVX, ενεργοποιήστε το «Άνοιγμα υποστηριζόμενων συνδέσμων» και τις υποστηριζόμενες διευθύνσεις ιστού. Άνοιγμα ρυθμίσεων προεπιλεγμένων εφαρμογών Προεπιλεγμένη ταχύτητα αναπαραγωγής Προεπιλεγμένη ποιότητα βίντεο με δεδομένα κινητής τηλεφωνίας @@ -187,6 +192,9 @@ Οι αριθμοί κινούνται αυξανόμενοι εκθετικά. Οι αριθμοί δεν κινούνται αυξανόμενοι εκθετικά. Απενεργοποίηση κινήσεων αριθμών + Το εφέ κίνησης πάνω από το κουμπί «Μου αρέσει» είναι ενεργοποιημένο. + Το εφέ κίνησης πάνω από το κουμπί «Μου αρέσει» είναι απενεργοποιημένο. + Απενεργοποίηση εφέ κουμπιού «Μου αρέσει» "Απενεργοποίηση του «Παίζοντας με 2x ταχύτητα» κατά το παρατεταμένο πάτημα. Σημειώσεις: @@ -201,12 +209,12 @@ • Πάτημα για κύλιση. • Παρατεταμένο πάτημα για επιλογή κειμένου." Απενεργοποίηση αλληλεπίδρασης περιγραφής βίντεο - Ο κωδικοποιητής VP9 είναι απενεργοποιημένος. - "Ο κωδικοποιητής VP9 είναι ενεργοποιημένος. + Ο κωδικοποιητής VP9 είναι ενεργοποιημένος. + "Ο κωδικοποιητής VP9 είναι απενεργοποιημένος. • Η μέγιστη ανάλυση είναι 1080p. • Η αναπαραγωγή βίντεο θα χρησιμοποιεί περισσότερα δεδομένα Internet από τον VP9. -• Για την αναπαραγωγή με ποιότητα HDR, τα βίντεο HDR εξακολουθούν να χρησιμοποιούν τον κωδικοποιητή VP9." +• Για την αναπαραγωγή βίντεο τύπου HDR, ο κωδικοποιητής VP9 εξακολουθεί να χρησιμοποιείται." Απενεργοποίηση κωδικοποιητή VP9 Η γραμμή προόδου του θέματος Cairo είναι απενεργοποιημένη. "Η γραμμή προόδου του θέματος Cairo είναι ενεργοποιημένη. @@ -307,6 +315,7 @@ Η περιγραφή βίντεο ανοίγεται αυτόματα. Αυτόματο άνοιγμα περιγραφής βίντεο Θέλετε να συνεχίσετε; + Επαναφέρθηκε στην προεπιλεγμένη τιμή. Επανεκκίνηση ώστε να φορτωθεί σωστά η διάταξη Ανανέωση και επανεκκίνηση Αποτυχία εξαγωγής ρυθμίσεων. @@ -498,7 +507,7 @@ Playlists Προωθήσεις YouTube Premium Εμφανίζονται. Κρυμμένα. - Γκρι διαχωριστικό + Γκρι διαχωριστικά Εμφανίζονται. Κρυμμένα. Ψευδώνυμο & διεύθυνση e-mail @@ -582,6 +591,9 @@ Playlists Εμφανίζεται. Κρυμμένη. Ενότητα ταινιών + Εμφανίζεται. + Κρυμμένη. + Γραμμή πλοήγησης Εμφανίζεται. Κρυμμένο. Κουμπί «Δημιουργία» @@ -747,6 +759,12 @@ Playlists Αφορά την ενότητα περισσότερων βίντεο στις γρήγορες ενέργειες και το σχετιζόμενο βίντεο. Σχετιζόμενο βίντεο + Εμφανίζονται. + Κρυμμένα. + Σχετιζόμενα βίντεο + "Αυτή η ρύθμιση περιορίζει τον μέγιστο αριθμό διατάξεων που μπορούν να εμφανιστούν στην οθόνη αναπαραγωγής. + +Στην περίπτωση που η διάταξη της οθόνης αναπαραγωγής αλλάξει λόγω αλλαγών από πλευράς του διακομιστή, ορισμένες διατάξεις της ενδέχεται να κρυφτούν χωρίς να είναι επιθυμητό." Εμφανίζεται. Κρυμμένο. Κουμπί «Remix» @@ -819,6 +837,9 @@ Playlists Εμφανίζεται. Κρυμμένη. Ετικέτα συνδέσμου πλήρους βίντεο + Εμφανίζεται. + Κρυμμένο. + Κουμπί «Πράσινη οθόνη» Εμφανίζονται. Κρυμμένα. Πάνελ πληροφοριών @@ -852,9 +873,9 @@ Playlists Εμφανίζεται. Κρυμμένο. Κουμπί «Remix» - Εμφανίζεται. - Κρυμμένο. - Κουμπί αποθήκευσης ήχου σε λίστα αναπαραγωγής + Εμφανίζεται. + Κρυμμένο. + Κουμπί «Αποθήκευση μουσικής» Εμφανίζεται. Κρυμμένο. Κουμπί προτάσεων αναζήτησης @@ -882,13 +903,16 @@ Playlists Κουμπί «Κατάστημα» Εμφανίζεται. Κρυμμένο. - Κουμπί «Κατάστημα» + Κουμπί «Αγορές» Εμφανίζεται. Κρυμμένο. Κουμπί ήχου Εμφανίζεται. Κρυμμένη. Ετικέτα μεταδεδομένων ήχου + Εμφανίζεται. + Κρυμμένα. + Αυτοκόλλητα Εμφανίζεται. Κρυμμένο. Κουμπί «Εγγραφή» @@ -963,15 +987,28 @@ Playlists Εμφανίζεται. Κρυμμένη. Ενότητα απομαγνητοφώνησης + "Απόκρυψη βίντεο με την ετικέτα «ΠΡΟΣΕΧΩΝ». + +Σημείωση: Η ενεργοποίηση αυτής της ρύθμισης θα κρύψει επίσης το κουμπί «Να λαμβάνω ειδοποιήσεις»." + Απόκρυψη προσεχών βίντεο Εμφανίζονται. Κρυμμένες. Διαφημίσεις βίντεο - Τα βίντεο με διάρκεια μεγαλύτερη από αυτόν τον αριθμό δεν θα εμφανίζονται. - Μέγιστο όριο διάρκειας - Τα βίντεο με διάρκεια μικρότερη από αυτόν τον αριθμό δεν θα εμφανίζονται. - Ελάχιστο όριο διάρκειας - Απόκρυψη των βίντεο με διάρκεια μικρότερη ή μεγαλύτερη από την προτίμησή σας.\n\nΓνωστό θέμα: Δε λειτουργεί στα προτεινόμενα βίντεο κάτω από τον αναπαραγωγέα, θα κρύβεται όμως η χρονοσφραγίδα τους. - Απόκρυψη βίντεο βάσει διάρκειάς τους + "Οι καρτέλες «Αρχική», «Εγγραφές» και τα αποτελέσματα αναζήτησης φιλτράρονται για απόκρυψη βίντεο με προβολές λιγότερες ή περισσότερες από τον καθορισμένο σας αριθμό. + +Περιορισμοί: +• Τα Shorts δε φιλτράρονται. +• Τα βίντεο με 0 προβολές δε φιλτράρονται." + Σχετικά με το φιλτράρισμα βάσει προβολών + Τα βίντεο στην καρτέλα «Αρχική» δε φιλτράρονται με βάση τον αριθμό προβολών. + Τα βίντεο στην καρτέλα «Αρχική» φιλτράρονται με βάση τον αριθμό προβολών. + Φιλτράρισμα καρτέλας «Αρχική» + Τα αποτελέσματα αναζήτησης δε φιλτράρονται με βάση τον αριθμό προβολών. + Τα αποτελέσματα αναζήτησης φιλτράρονται με βάση τον αριθμό προβολών. + Φιλτράρισμα αποτελεσμάτων αναζήτησης + Τα βίντεο στην καρτέλα «Εγγραφές» δε φιλτράρονται με βάση τον αριθμό προβολών. + Τα βίντεο στην καρτέλα «Εγγραφές» φιλτράρονται με βάση τον αριθμό προβολών. + Φιλτράρισμα καρτέλας «Εγγραφές» Απόκρυψη των βίντεο με προβολές λιγότερες ή περισσότερες από την προτίμησή σας.\n\nΓνωστό θέμα: Τα βίντεο με 0 προβολές δε φιλτράρονται σωστά. Απόκρυψη βίντεο βάσει αριθμού προβολών Τα βίντεο με περισσότερες προβολές από αυτόν τον αριθμό δεν θα εμφανίζονται. @@ -1024,7 +1061,7 @@ Playlists Εμφανίζονται. Κρυμμένα. Κείμενα οθόνης αναπαραγωγής - Η αδιαφάνεια πρέπει να ναι μεταξύ 0-100, επαναφέρθηκε. + Η αδιαφάνεια πρέπει να ναι μεταξύ 0-100. Τιμή αδιαφάνειας μεταξύ 0-100, όπου το 0 είναι διαφανές. Αδιαφάνεια φόντου παρασκηνίου Αρχική @@ -1073,13 +1110,18 @@ Playlists Το κουμπί λήψης του YouTube ανοίγει το εγγενές πρόγραμμα λήψης της εφαρμογής. Το κουμπί λήψης του YouTube ανοίγει το εξωτερικό πρόγραμμα λήψης σας. Μετατροπή κουμπιού λήψης βίντεο + Το YouTube Music είναι απαραίτητο για την μετατροπή ενέργειας του κουμπιού. Πατήστε για να κατεβάσετε το YouTube Music. + Προαπαιτούμενο + Το κουμπί YouTube Music ανοίγει την εγγενή εφαρμογή. + Το κουμπί YouTube Music ανοίγει τo RVX Music. + Μετατροπή κουμπιού YouTube Music Εξαιρέθηκε Συμπεριλήφθηκε Κανονική Κουμπιά ενεργειών Πρόσθετες ρυθμίσεις Εφέ / Απόκριση - Φίλτρο διάρκειας + Κουμπί «Λήψη» Πειραματικές Λειτουργίες Περιορισμοί περιοχής εικόνων Εισαγωγή / Εξαγωγή ως αρχείο @@ -1091,6 +1133,7 @@ Playlists Γρήγορες ενέργειες Προτεινόμενα βίντεο Ενότητα Shorts + Προτεινόμενες ενέργειες Χρησιμοποιούμενο εργαλείο Φίλτρο αριθμού προβολών Απόκρυψη ή εμφάνιση στοιχείων στο μενού λογαριασμού και στην καρτέλα «Εσείς». @@ -1121,13 +1164,15 @@ Playlists Γενικά Απενεργοποίηση η ενεργοποίηση απόκρισης δόνησης. Απόκριση δόνησης + Μετατροπή ενέργειας πατήματος των κουμπιών της εφαρμογής. + Μετατροπή κουμπιών Εισαγωγή ή εξαγωγή των ρυθμίσεων σας. Εισαγωγή / Εξαγωγή ρυθμίσεων Αλλαγή του στυλ της ελαχιστοποιημένης οθόνης αναπαραγωγής. Ελαχιστοποιημένη οθόνη αναπαραγωγής Διάφορα - Απόκρυψη ή εμφάνιση στοιχείων της γραμμής πλοήγησης. - Κουμπιά πλοήγησης + Απόκρυψη ή εμφάνιση των στοιχείων της γραμμής πλοήγησης. + Γραμμή πλοήγησης Πληροφορίες σχετικά με τις εφαρμοσμένες τροποποιήσεις. Πληροφορίες τροποποίησης Απόκρυψη ή εμφάνιση κουμπιών στην οθόνη αναπαραγωγής βίντεο. @@ -1156,13 +1201,14 @@ Playlists Βίντεο Διαχείριση των ρυθμίσεων που σχετίζονται με το ιστορικό παρακολούθησης. Ιστορικό παρακολούθησης - Το ύψος πρέπει να είναι μεταξύ 0-32, επαναφέρθηκε. + Το ύψος πρέπει να είναι μεταξύ 0-32. Αλλαγή ύψους της γραμμής προόδου, τιμές μεταξύ 0-32. Ύψος γραμμής προόδου "Εξαναγκαστική απόρριψη της απόκρισης του κωδικοποιητή λογισμικού AV1. Μετά από περίπου 20 δευτερόλεπτα φόρτωσης, θα γίνεται αλλαγή σε διαφορετικό κωδικοποιητή." Απόρριψη απόκρισης κωδικοποιητή AV1 Η διαδικασία προκαλεί περίπου 20 δευτερόλεπτα φόρτωσης. + Μετατόπιση Οι αλλαγές ταχύτητας αναπαραγωγής ισχύουν μόνο για το τρέχον βίντεο. Οι αλλαγές ταχύτητας αναπαραγωγής ισχύουν για όλα τα βίντεο. Απομνημόνευση αλλαγών ταχύτητας αναπαραγωγής @@ -1421,9 +1467,12 @@ Playlists Καρδιά (χρωματιστή) Τίποτα Εφέ διπλού πατήματος - Το βάθος πρέπει να είναι μεταξύ 0-64, επαναφέρθηκε. + Το βάθος πρέπει να είναι μεταξύ 0-64. Αλλαγή βάθους της γραμμής προόδου, τιμές μεταξύ 0-64. Βάθος γραμμής προόδου + Το ποσοστό ύψους πρέπει να είναι μεταξύ 0-100 (%). + Ρύθμιση του ποσοστού ύψους του κενού χώρου που απομένει όταν η γραμμή πλοήγησης είναι κρυμμένη, μεταξύ 0 και 100 (%). + Ποσοστό ύψους του κενού χώρου Πατήστε παρατεταμένα την χρονοσφραγίδα για να αλλάξει η κατάσταση επανάληψης των Shorts. Ενέργεια πατήματος χρονοσφραγίδας "Εμφάνιση τίτλου του βίντεο σε πλήρη οθόνη. @@ -1443,15 +1492,15 @@ Playlists Εμφάνιση μηνύματος κατά την παράλειψη Η ενεργοποίηση αυτής της ρύθμισης μπορεί να προκαλέσει προβλήματα αναπαραγωγής βίντεο. Η προφόρτωση βίντεο παραλείφθηκε. - Η ταχύτητα πρέπει να ναι μεταξύ 0-8.0, επαναφέρθηκε. + Η ταχύτητα πρέπει να ναι μεταξύ 0-8.0. Τιμή ταχύτητας που εφαρμόζεται κατά το παρατεταμένο πάτημα, μεταξύ 0 και 8.0. Τιμή διεπαφής ταχύτητας "Τροποποίηση έκδοσης της εφαρμογής σε παλιότερη έκδοση. Αυτό θα αλλάξει την εμφάνιση της εφαρμογής, αλλά ενδέχεται να προκύψουν άγνωστες παρενέργειες. Εάν αργότερα απενεργοποιηθεί, η παλιά εμφάνιση μπορεί να παραμείνει μέχρι να διαγραφούν τα δεδομένα της εφαρμογής." - Η έκδοση δεν τροποποιείται - Η έκδοση τροποποιείται + Η έκδοση δεν τροποποιείται. + Η έκδοση τροποποιείται. 17.33.42 - Επαναφορά της παλιάς εμφάνισης 17.41.37 - Επαναφορά ενότητας λίστας αναπαραγωγής στο παλιό στυλ 18.05.40 - Επαναφορά πλαισίου εισαγωγής σχολίων στο παλιό στυλ @@ -1477,10 +1526,14 @@ Playlists "Ενεργοποιώντας αυτόν τον κωδικοποιητή ίσως βελτιωθεί η κατανάλωση ενέργειας και ίσως διορθωθούν μικροκολλήματα αναπαραγωγής. Ο AVC (H.264) ωστόσο έχει μέγιστη ανάλυση 1080p, και η αναπαραγωγή βίντεο καταναλώνει περισσότερα δεδομένα internet από τον VP9 ή τον AV1." - • Το μενού «Κομμάτι ήχου» λείπει. - • Το μενού «Κομμάτι ήχου» λείπει. + "• Το μενού «Κομμάτι ήχου» λείπει. +• Η λειτουργία «Σταθερή ένταση» δεν είναι διαθέσιμη." + "• Το μενού «Κομμάτι ήχου» λείπει. +• Η λειτουργία «Σταθερή ένταση» δεν είναι διαθέσιμη." "• Οι ταινίες ή τα επί πληρωμή βίντεο ενδέχεται να μην αναπαράγονται. -• Οι ζωντανές μεταδόσεις ξεκινούν από την αρχή κατά την αναπαραγωγή." +• Οι ζωντανές μεταδόσεις ξεκινούν από την αρχή κατά την αναπαραγωγή. +• Τα βίντεο μπορεί να τελειώνουν 1 δευτερόλεπτο νωρίτερα. +• Ο κωδικοποιητής ήχου opus δεν είναι διαθέσιμος." Παρενέργειες παραποίησης • Τα βίντεο ενδέχεται να μην αναπαράγονται. Το πρόγραμμα πελάτη που χρησιμοποιείται για τη λήψη δεδομένων ροής δεν εμφανίζεται στο μενού «Στατιστικά για σπασίκλες». @@ -1503,7 +1556,7 @@ Playlists Κατώτατο όριο μεγέθους σάρωσης Η ορατότητα του φόντου σάρωσης στο παρασκήνιο. Ορατότητα φόντου σάρωσης - Το μέγεθος οθόνης πρέπει να ναι μικρότερο από 50, επαναφέρθηκε. + Το μέγεθος οθόνης πρέπει να ναι μικρότερο από 50. Ποσοστό επιφάνειας της οθόνης που μπορεί να γίνει η σάρωση.\n\nΣημείωση: Αυτό θα αλλάξει επίσης το μέγεθος της περιοχής οθόνης της χειρονομίας διπλού πατήματος για αναζήτηση. Μέγεθος περιοχής οθόνης σάρωσης Το μέγεθος κειμένου στοιχείων ελέγχου του φόντου σάρωσης. @@ -1519,15 +1572,19 @@ Playlists Σημείωση: Η ενεργοποίηση αυτής της ρύθμισης εξαναγκάζει επίσης την απόκρυψη των διαφημίσεων βίντεο." Εναλλαγή «Δημιουργία» με «Ειδοποιήσεις» - "Η απενεργοποίηση αυτής της ρύθμισης μπορεί να χει ως αποτέλεσμα την φόρτωση περισσότερων διαφημίσεων από τον διακομιστή. + "Η απενεργοποίηση αυτής της ρύθμισης μπορεί να έχει ως αποτέλεσμα την φόρτωση περισσότερων διαφημίσεων από τον διακομιστή. Επίσης, ενδέχεται να εμφανίζονται διαφημίσεις στα Shorts. Αν η απενεργοποίηση δεν τεθεί σε ισχύ, δοκιμάστε να μεταβείτε σε λειτουργία ανώνυμης περιήγησης." Προεπιλογή + RVX Music + %s δεν έχει εγκατασταθεί. Παρακαλούμε εγκαταστήστε το. + Όνομα πακέτου του εγκατεστημένου RVX Music. + Όνομα πακέτου RVX Music Το ιστορικό παρακολούθησης είναι αποκλεισμένο. "• Ακολουθούνται οι ρυθμίσεις ιστορικού παρακολούθησης του λογαριασμού Google σας. -• Το ιστορικό παρακολούθησης μπορεί να μη λειτουργεί λόγω του DNS ή χρήσης VPN." +• Το ιστορικό παρακολούθησης μπορεί να μη λειτουργεί λόγω του DNS σας ή χρήσης VPN." • Ακολουθούνται οι ρυθμίσεις ιστορικού παρακολούθησης του λογαριασμού Google σας. Κατάσταση ιστορικού παρακολούθησης Πατήστε για άνοιγμα της διαχείρισης του ιστορικού παρακολούθησης του YouTube. diff --git a/src/main/resources/youtube/translations/es-rES/missing_strings.xml b/src/main/resources/youtube/translations/es-rES/missing_strings.xml index b3c19545c..d514aa21f 100644 --- a/src/main/resources/youtube/translations/es-rES/missing_strings.xml +++ b/src/main/resources/youtube/translations/es-rES/missing_strings.xml @@ -2,7 +2,6 @@ Don\'t show again Courses / Learning - Playables Package name of your installed external downloader app, such as NewPipe or YTDLnis, on long press. Long press video downloader package name Displays the optimization dialog for GMSCore at each application startup. @@ -10,13 +9,11 @@ Disabled comments button or with label \"0\" is shown. Disabled comments button or with label \"0\" is hidden. Hide disabled comments button - "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. - -Limitations: -• Shorts cannot be hidden. -• Videos with 0 views are not filtered." MMT Blue MMT Green + MMT Orange + MMT Pink + MMT Turquoise MMT Yellow Revancify Yellow Vanced Black diff --git a/src/main/resources/youtube/translations/es-rES/strings.xml b/src/main/resources/youtube/translations/es-rES/strings.xml index d13aa04d5..921787f73 100644 --- a/src/main/resources/youtube/translations/es-rES/strings.xml +++ b/src/main/resources/youtube/translations/es-rES/strings.xml @@ -22,6 +22,7 @@ Si se activa, las URL de vídeo se enviarán al servidor API y no se enviará ni Pulsa aquí para saber más sobre DeArrow." DeArrow + URL de la API de DeArrow no válida. La URL del punto final de la caché de miniaturas de DeArrow. Punto final de la API de DeArrow No se muestra el mensaje si DeArrow no está disponible. @@ -89,8 +90,12 @@ Pulsa aquí para saber más sobre DeArrow." Suscripciones Tendencias Ver más tarde - Página de inicio no válida, restableciendo a la predeterminada. Cambiar página de inicio + La página de inicio solo cambia una vez. + "La página de inicio siempre cambia. + +Limitación: Es posible que el botón Atrás de la barra de herramientas no funcione." + Cambiar tipo de página de inicio La cabecera genérica está activada. La cabecera Premium está activada. Cambiar cabecera de YouTube @@ -187,6 +192,9 @@ Limitación: Es posible que este ajuste no se aplique a los vídeos que no inclu Los números rodantes están animados. Los números rodantes no están animados. Desactivar animaciones de números rodantes + La animación de la fuente está activada sobre el botón de me gusta. + La animación de la fuente está desactivada sobre el botón de me gusta. + Desactivar animación del botón de me gusta "Desactiva \"Reproducir a velocidad x2\" mientras mantienes pulsado. Nota: @@ -306,6 +314,7 @@ Estos caracteres varían dependiendo de tu idioma. La descripción del vídeo se expande automáticamente. Expandir descripción de vídeo ¿Quieres continuar? + Restablecer valores predeterminados. Reiniciar para cargar el diseño normalmente Actualizar y reiniciar Error al exportar los ajustes. @@ -572,6 +581,9 @@ Las palabras con letras mayúsculas en el medio deben introducirse con las mayú Los estantes de películas están visibles. Los estantes de películas están ocultos. Ocultar estantes de películas + La barra de navegación está visible. + La barra de navegación está oculta. + Ocultar barra de navegación El botón de crear está visible. El botón de crear está oculto. Ocultar botón de crear @@ -734,6 +746,12 @@ Las palabras con letras mayúsculas en el medio deben introducirse con las mayú La superposición de vídeo relacionado está visible. La superposición de vídeo relacionado está oculta. Ocultar superposición de vídeo relacionado + Los vídeos relacionados están visibles. + Los vídeos relacionados están ocultos. + Ocultar vídeos relacionados + "Este ajuste limita el número máximo de diseños que se pueden cargar en la pantalla del reproductor. + +Si el diseño de la pantalla del reproductor cambia debido a cambios en el servidor, es posible que se oculten diseños no deseados en la pantalla del reproductor." El botón de remix está visible. El botón de remix está oculto. Ocultar botón de remix @@ -795,6 +813,9 @@ Subtítulos" La etiqueta de enlace de vídeo está visible. La etiqueta de enlace de vídeo está oculta. Ocultar etiqueta de enlace de vídeo completo + El botón de la pantalla verde está visible. + El botón de la pantalla verde está oculto. + Ocultar botón de pantalla verde Los paneles de información están visibles. Los paneles de información están ocultos. Ocultar paneles de información @@ -828,9 +849,9 @@ Subtítulos" El botón de remix está visible. El botón de remix está oculto. Ocultar botón de remix - El botón de guardar sonido está visible. - El botón de guardar sonido está oculto. - Ocultar botón de guardar sonido + El botón de guardar música está visible. + El botón de guardar música está oculto. + Ocultar botón de guardar música El botón de sugerencias de búsqueda está visible. El botón de sugerencias de búsqueda está oculto. Ocultar botón de sugerencias de búsqueda @@ -865,6 +886,9 @@ Limitación: las cabeceras oficiales en los resultados de búsqueda estarán ocu La etiqueta de metadatos está visible. La etiqueta de metadatos está oculta. Ocultar etiqueta de metadatos de sonido + Los stickers están visibles. + Los stickers están ocultos. + Ocultar stickers El botón de suscribirse está visible. El botón de suscribirse está oculto. Ocultar botón de suscribirse @@ -937,15 +961,18 @@ La reproducción automática se puede cambiar en la configuración de YouTube: Las secciones de transcripción están visibles. Las secciones de transcripción están ocultas. Ocultar secciones de transcripción + "Oculta vídeos con la etiqueta PRÓXIMAMENTE. + +Nota: Al activar esta opción también se oculta el botón de notificarme." + Ocultar vídeo PRÓXIMO Los anuncios de vídeo están visibles. Los anuncios de vídeo están ocultos. Ocultar anuncios de vídeo - Los vídeos con una duración más larga que este número serán ocultados. - Duración más larga - Los vídeos con una duración más corta que este número serán ocultados. - Duración más corta - Oculta vídeos con una duración inferior o superior a la establecida.\n\nProblema conocido: no ocultará los vídeos en los vídeos relacionados en el reproductor, en su lugar ocultará la marca de tiempo. - Ocultar vídeos basados en la duración + "El inicio / Las suscripciones / Los resultados de búsqueda se filtran para ocultar los vídeos con visualizaciones inferiores o superiores a un número determinado. + +Limitaciones: +• Los Shorts no se pueden ocultar. +• Los vídeos con 0 visualizaciones no se filtran." Acerca del filtrado del contador de visualizaciones Los vídeos en el feed de inicio no están filtrados. Los vídeos en el feed de inicio están filtrados. @@ -1049,13 +1076,18 @@ Toque y mantenga presionado para abrir el diálogo de configuración de la lista El botón nativo de descarga de vídeo abre el descargador nativo de la aplicación. El botón nativo de descarga de vídeo abre tu descargador externo. Reemplazar botón de descarga de vídeo + Se requiere YouTube Music para reemplazar la acción del botón. Pulsa aquí para descargar YouTube Music. + Requisito previo + El botón de Youtube Music abre la app nativa. + El botón de YouTube Music abre RVX Music. + Reemplazar botón de YouTube Music Excluidos Incluidos Normal Botones de acción Ajustes adicionales Animación / Comentarios - Filtro de duración + Botón de descarga Funciones experimentales Restricciones de región de imágenes Importar / Exportar como archivo @@ -1067,6 +1099,7 @@ Toque y mantenga presionado para abrir el diálogo de configuración de la lista Acciones rápidas Vídeos recomendados Estantes de Shorts + Acciones sugeridas Herramientas utilizadas Filtro de contador de visualizaciones Ocultar o mostrar elementos en el menú de la cuenta y la pestaña Tú. @@ -1097,13 +1130,15 @@ Toque y mantenga presionado para abrir el diálogo de configuración de la lista General Desactiva o activa la vibración. Vibración + Reemplaza la acción de clic de los botones dentro de la aplicación. + Botones de enganche Importar o exportar los ajustes. Importar / Exportar ajustes Cambia el estilo del reproductor minimizado de la aplicación. Minirreproductor Otros - Ocultar o mostrar los componentes de la sección de la barra de navegación. - Botones de navegación + Ocultar o mostrar los componentes de la sección de la barra de navegación. + Barra de navegación Información sobre los parches aplicados. Información de parches Ocultar o mostrar botones en vídeos. @@ -1139,6 +1174,7 @@ Toque y mantenga presionado para abrir el diálogo de configuración de la lista Después de unos 20 segundos de búfer, cambia a un códec diferente." Rechazar respuesta del códec AV1 del software El proceso de Fallback causa unos 20 segundos de búfer. + Desplazamiento Los cambios de velocidad de reproducción solo se aplican al vídeo actual. Los cambios de velocidad de reproducción se aplican a todos los vídeos. Recordar cambios de velocidad de reproducción @@ -1401,6 +1437,9 @@ Limitación: es posible que los no me gusta no aparezcan en modo incógnito."El margen inferior del panel meta debe estar entre 0-64. Restablezca a los valores predeterminados. Configura el espaciado desde la barra de progreso al panel meta, entre 0-64. Margen inferior del panel meta + El porcentaje de altura debe estar entre 0-100 (%). + Configura el porcentaje de altura del espacio vacío izquierdo cuando la barra de navegación está oculta, entre 0 y 100 (%). + Porcentaje de altura del espacio vacío Mantén pulsada la marca de tiempo para cambiar el estado de repetición de los Shorts. Acción de pulsación larga en marca de tiempo "Muestra la sección de título de vídeo en pantalla completa. @@ -1453,8 +1492,8 @@ Si se desactiva más tarde, se recomienda borrar los datos de la aplicación par "Activar esto podría mejorar la duración de la batería y solucionar el problema de reproducción entrecortada. AVC (H.264) tiene una resolución máxima de 1080p, y la reproducción de vídeo utilizará más datos de Internet que VP9 o AV1." - • Falta el menú de la pista de audio. - • Falta el menú de la pista de audio. + "• Falta el menú de la pista de audio." + "• Falta el menú de la pista de audio." "• Las películas o vídeos de pago no pueden reproducirse." Efectos secundarios de falsificación • El vídeo no puede reproducirse. @@ -1501,6 +1540,10 @@ Además, los anuncios ya no se bloquearán en Shorts. Si este ajuste no surte efecto, prueba a cambiar al modo incógnito." Predeterminado + RVX Music + %s no está instalado. Por favor, instálalo. + Nombre del paquete de RVX Music instalado. + Nombre del paquete de RVX Music • El historial de reproducciones no funciona. "• Sigue la configuración del historial de reproducciones de la cuenta de Google. • Es posible que el historial de reproducciones no funcione debido a DNS o VPN." diff --git a/src/main/resources/youtube/translations/fi-rFI/missing_strings.xml b/src/main/resources/youtube/translations/fi-rFI/missing_strings.xml index 50d7e1f33..c8a03773a 100644 --- a/src/main/resources/youtube/translations/fi-rFI/missing_strings.xml +++ b/src/main/resources/youtube/translations/fi-rFI/missing_strings.xml @@ -1,6 +1,7 @@ Don\'t show again + Invalid DeArrow API URL. Still video captures The domain to fetch images from.\nNote: Only enter the domain name, i.e., without the \"https\:\/\/\" prefix. Alternative domain @@ -16,11 +17,14 @@ Live Movies Music - Playables Sports Watch later - Invalid start page, resetting to default. - Player overlay opacity must be between 0-100. Reset to default values. + Start page changes only once. + "Start page always changes. + +Limitation: Back button on the toolbar may not work." + Change start page type + Player overlay opacity must be between 0-100. Ambient mode is enabled in fullscreen. Ambient mode is disabled in fullscreen. Ambient mode is enabled. @@ -40,12 +44,15 @@ Limitation: This setting may not apply to videos that do not include the 'Listen Like and Dislike buttons will glow when mentioned. Like and Dislike buttons will not glow when mentioned. Disable Like and Dislike button glow + Fountain animation is enabled above the Like button. + Fountain animation is disabled above the Like button. + Disable Like button animation VP9 codec is enabled. "VP9 codec is disabled. • Maximum resolution is 1080p. • Video playback will use more internet data than VP9. -• To get HDR playback, HDR video still uses the VP9 codec." +• VP9 codec is still used for HDR video." Disable VP9 codec Cairo seekbar is disabled. "Cairo seekbar is enabled. @@ -71,6 +78,7 @@ Limitations: Navigation bar is translucent. Enable translucent navigation bar Do you wish to proceed? + Reset to default values. Search %s Package name of your installed external downloader app, such as YTDLnis. Playlist downloader package name @@ -117,6 +125,9 @@ Side effect: Community post images may be blocked in fullscreen." Hide live chat replay button Hide videos with less than 1,000 views from home feeds that have been uploaded from unsubscribed channels. Hide low views video + Navigation bar is shown. + Navigation bar is hidden. + Hide navigation bar Ambient mode menu is shown. Ambient mode menu is hidden. Hide Ambient mode menu @@ -129,12 +140,21 @@ Side effect: Community post images may be blocked in fullscreen." Promotion alert banner is shown. Promotion alert banner is hidden. Hide promotion alert banner + Related videos are shown. + Related videos are hidden. + Hide related videos + "This setting limits the maximum number of layouts that can be loaded on the player screen. + +If the layout of the player screen changes due to server-side changes, unintended layouts may be hidden on the player screen." Disabled comments button or with label \"0\" is shown. Disabled comments button or with label \"0\" is hidden. Hide disabled comments button "Floating buttons like 'Use this sound' are shown in the Shorts channel tab." "Floating buttons like 'Use this sound' are hidden in the Shorts channel tab." Hide floating button + Green screen button is shown. + Green screen button is hidden. + Hide Green screen button Live chat header is shown.\n\nBack button in header will not be hidden. Live chat header is hidden.\n\nBack button in header will not be hidden. Hide live chat header @@ -147,12 +167,18 @@ Side effect: Community post images may be blocked in fullscreen." Button background is shown. Button background is hidden. Hide Play & Pause button background + Save music button is shown. + Save music button is hidden. + Hide Save music button Search suggestions button is shown. Search suggestions button is hidden. Hide search suggestions button Shopping button is shown. Shopping button is hidden. Hide Shopping button + Stickers are shown. + Stickers are hidden. + Hide stickers Super Thanks button is shown. Super Thanks button is hidden. Hide Super Thanks button @@ -173,6 +199,10 @@ Side effect: Community post images may be blocked in fullscreen." Autoplay can be changed in YouTube settings: Settings → Autoplay → Autoplay next video" + "Hide videos with UPCOMING label. + +Note: Enabling this also hides the Notify me button." + Hide UPCOMING video "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. Limitations: @@ -195,6 +225,9 @@ Limitations: Afn Red MMT Blue MMT Green + MMT Orange + MMT Pink + MMT Turquoise MMT Yellow Revancify Yellow Vanced Black @@ -219,7 +252,7 @@ Limitations: Subtexts are shown. Subtexts are hidden. Hide subtexts - Miniplayer overlay opacity must be between 0-100. Reset to default values. + Miniplayer overlay opacity must be between 0-100. Opacity value between 0-100, where 0 is transparent. Overlay opacity Original @@ -243,15 +276,27 @@ Tap and hold to open whitelist setting dialog. Native video download button opens the native in-app downloader. Native video download button opens your external downloader. Override video download button + YouTube Music is required to override button action. Tap here to download YouTube Music. + Prerequisite + YouTube Music button opens the native app. + YouTube Music button opens the RVX Music. + Override YouTube Music button Animation / Feedback + Download button Image region restrictions + Suggested actions + Overrides the click action of in-app buttons. + Hook buttons Change the style of the in app minimized player. Miniplayer + Hide or show navigation bar section components. + Navigation bar Spoof the streaming data to prevent playback issues. Spoof streaming data Change settings related with watch history. Watch history - Quick actions top margin must be between 0-32. Reset to default values. + Quick actions top margin must be between 0-32. + Offset A toast will not be shown when changing the default playback speed. A toast will be shown when changing the default playback speed. Show a toast @@ -277,15 +322,21 @@ Tap and hold to open whitelist setting dialog. Heart (Tint) Hidden Double-tap animation - Meta panel bottom margin must be between 0-64. Reset to default values. + Meta panel bottom margin must be between 0-64. Configure the spacing from the seekbar to the meta panel, between 0-64. Meta panel bottom margin + Height percentage must be between 0-100 (%). + Configure the height percentage of the empty space left when the navigation bar is hidden, between 0 and 100 (%). + Height percentage of empty space Press and hold the timestamp to change the Shorts repeat status. Timestamp long press action Turning on this setting may cause video playback issues. - Speed overlay value must be between 0-8.0. Reset to default values. + Speed overlay value must be between 0-8.0. Version not spoofed Version spoofed + 18.33.40 - Restore old Shorts action bar + 18.38.45 - Restore old default video quality behavior + 18.48.39 - Disables views and likes from being updated in real time "App version will be spoofed to an older version of YouTube. This will change the appearance and features of the app, but unknown side effects may occur. @@ -297,10 +348,14 @@ If later turned off, it is recommended to clear the app data to prevent UI bugs. "Enabling this might improve battery life and fix playback stuttering. AVC (H.264) has a maximum resolution of 1080p, and video playback will use more internet data than VP9 or AV1." - • Audio track menu is missing. - • Audio track menu is missing. + "• Audio track menu is missing. +• Stable volume is not available." + "• Audio track menu is missing. +• Stable volume is not available." "• Movies or paid videos may not play. -• Livestreams start from the beginning." +• Livestreams start from the beginning. +• Videos may end 1 second early. +• No opus audio codec." Spoofing side effects • Video may not play. Client used to fetch streaming data is hidden in Stats for nerds. @@ -315,7 +370,7 @@ AVC (H.264) has a maximum resolution of 1080p, and video playback will use more iOS Default client Turning off this setting may cause video playback issues. - Swipeable area size cannot be more than 50. Reset to default value. + Swipeable area size cannot be more than 50. Percentage of swipeable screen area.\n\nNote: This will also change the size of the screen area for the double-tap-to-seek gesture. Swipe overlay screen size Create button is not switched with Notifications button. @@ -327,6 +382,10 @@ Note: Enabling this also forcibly hides video ads." Also, ads will no longer be blocked in Shorts. If this setting do not take effect, try switching to Incognito mode." + RVX Music + %s is not installed. Please install it. + Package name of installed RVX Music. + RVX Music package name • Watch history is blocked. "• Follows the watch history settings of Google account. • Watch history may not work due to DNS or VPN." diff --git a/src/main/resources/youtube/translations/fi-rFI/strings.xml b/src/main/resources/youtube/translations/fi-rFI/strings.xml index 14ab3677c..a6bc0bb44 100644 --- a/src/main/resources/youtube/translations/fi-rFI/strings.xml +++ b/src/main/resources/youtube/translations/fi-rFI/strings.xml @@ -691,9 +691,6 @@ Captions" Remix button is shown. Remix button is hidden. Hide remix button - Save sound to playlist is shown. - Save sound to playlist is hidden. - Hide save sound to playlist button Share button is shown. Share button is hidden. Hide share button @@ -780,12 +777,6 @@ Note: Video ads are shown. Video ads are hidden. Hide video ads - Videos with duration longer than this number will be hidden. - Longer than duration - Videos with duration shorter than this number will be hidden. - Shorter than duration - Hide videos with shorter than or longer than duration.\n\nKnown issue: It will not hide videos in the player related videos, instead it will hide the timestamp. - Hide videos based on duration Hide recommended videos with less than a specified number of views. Hide recommended videos by views Videos with views greater than this number will be hidden. @@ -836,7 +827,6 @@ Tap and hold to set playback speed to 1.0x." Normal Action buttons Additional settings - Duration filter Experimental Flags Import / Export as file Import / Export as text @@ -880,8 +870,6 @@ Tap and hold to set playback speed to 1.0x." Import or export settings. Import / Export settings Miscellaneous - Hide or show navigation bar section components. - Navigation buttons Information about applied patches. Patch information Hide or show buttons in videos. @@ -1177,9 +1165,6 @@ Limitation: Video title disappears when clicked." 17.41.37 - Restore old playlist shelf 18.05.40 - Restore old comment input box 18.17.43 - Restore old player flyout panel - 18.33.40 - Restore old shorts action bar - 18.38.45 - Restore old default video quality behavior - "18.48.39 - Disables 'views' and 'likes' from being updated in real time" Spoof app version target Type the spoof app version target. Edit spoof app version diff --git a/src/main/resources/youtube/translations/fr-rFR/missing_strings.xml b/src/main/resources/youtube/translations/fr-rFR/missing_strings.xml index 1da9ef507..d514aa21f 100644 --- a/src/main/resources/youtube/translations/fr-rFR/missing_strings.xml +++ b/src/main/resources/youtube/translations/fr-rFR/missing_strings.xml @@ -2,7 +2,6 @@ Don\'t show again Courses / Learning - Playables Package name of your installed external downloader app, such as NewPipe or YTDLnis, on long press. Long press video downloader package name Displays the optimization dialog for GMSCore at each application startup. @@ -10,23 +9,11 @@ Disabled comments button or with label \"0\" is shown. Disabled comments button or with label \"0\" is hidden. Hide disabled comments button - "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. - -Limitations: -• Shorts cannot be hidden. -• Videos with 0 views are not filtered." - About view count filtering - Videos in home feed are not filtered. - Videos in home feed are filtered. - Hide home videos by views - Search results are not filtered. - Search results are filtered. - Hide search results by views - Videos in subscriptions feed are not filtered. - Videos in subscriptions feed are filtered. - Hide subscription videos by views MMT Blue MMT Green + MMT Orange + MMT Pink + MMT Turquoise MMT Yellow Revancify Yellow Vanced Black diff --git a/src/main/resources/youtube/translations/fr-rFR/strings.xml b/src/main/resources/youtube/translations/fr-rFR/strings.xml index 2a8735e9b..42e1a243c 100644 --- a/src/main/resources/youtube/translations/fr-rFR/strings.xml +++ b/src/main/resources/youtube/translations/fr-rFR/strings.xml @@ -22,6 +22,7 @@ Si activée, l'URL des vidéos seront envoyés sur le serveur API et aucune autr Cliquez ici pour en savoir plus sur DeArrow." DeArrow + URL de l\'API DeArrow invalide. L\'URL du point de connexion au cache des miniatures DeArrow. Point de connexion à l\'API DeArrow N\'affiche pas de message si DeArrow est indisponible. @@ -89,8 +90,12 @@ Cliquez ici pour en savoir plus sur DeArrow." Abonnements Tendances Regarder plus tard - Page de démarrage invalide, valeur réinitialisée par défaut. Modifier la page de démarrage + La page de démarrage est modifiée une seule fois. + "La page de démarrage est toujours modifiée. + +Limitation : Le bouton Retour de la barre d'outils peut ne pas fonctionner." + Type de modification de la page de démarrage L\'en-tête original est activé. L\'en-tête YouTube Premium est activé. Changer l\'en-tête YouTube @@ -103,11 +108,11 @@ Cliquez ici pour en savoir plus sur DeArrow." L\'ancien style du menu déroulant est utilisé. Affichage de sélection de vitesse personnalisé. Personnaliser le menu \"Vitesse de lecture\" - Les vitesses personnalisées doivent être inférieures à %sx. Valeur réinitialisée par défaut. - Vitesses de lecture invalides. Valeur réinitialisée par défaut. + Les vitesses personnalisées doivent être inférieures à %sx. + Valeur des vitesses de lecture invalide. Ajouter ou modifier les vitesses de lecture disponibles. Saisir des vitesses de lecture personnalisées - L\'opacité du voile du lecteur doit être entre 0-100. Valeur réinitialisée par défaut. + L\'opacité du voile du lecteur doit être entre 0-100. Valeur d\'opacité entre 0-100, 0 étant transparent. Personnaliser l\'opacité du voile du lecteur Saisissez le code hexadécimal de la couleur de la barre de progression. @@ -187,6 +192,9 @@ Limitation : Ce paramètre peut ne pas s'appliquer aux vidéos qui n'incluent pa Animation en temps réel des nombres est activé. Animation en temps réel des nombres est désactivé. Animation en temps réel des nombres + L\'animation en cascade est activé pour le bouton j\'aime. + L\'animation en cascade est désactivé pour le bouton j\'aime. + Désactiver l\'animation du bouton j\'aime "Désactive '2x>>' en appuyant longuement. Note : @@ -206,7 +214,7 @@ Note : • La résolution maximale est en 1080p. • La lecture vidéo utilisera plus de données internet que le VP9. -• Pour utiliser la lecture en HDR, les vidéos HDR utilisent toujours le codec VP9." +• Le codec VP9 est également utilisé pour les vidéos HDR." Désactiver le codec VP9 La barre de progression Cairo est désactivé. "La barre de progression Cairo est activé. @@ -305,6 +313,7 @@ L'option \"Ouvrir la description automatiquement\" risque de ne pas fonctionner La description s\'ouvre automatiquement. Ouvrir la description automatiquement Voulez-vous continuer ? + Réinitialiser les valeurs par défaut. Redémarrer pour charger l\'interface correctement Appliquer et redémarrer ? Échec de l\'exportation des paramètres. @@ -574,6 +583,9 @@ Les mots comportant des majuscules au milieu doivent être saisis de la même fa Les étagères \"Vos films et séries\" sont affichés. Les étagères \"Vos films et séries\" sont masqués. Masquer \"Vos films et séries\" + La barre de navigation est affichée. + La barre de navigation est masqué. + Masquer la barre de navigation Le bouton \"Créer\" est affiché. Le bouton \"Créer\" est masqué. Masquer le bouton \"Créer\" @@ -735,6 +747,12 @@ Les mots comportant des majuscules au milieu doivent être saisis de la même fa La section \'Plus de vidéos\' dans l\'action rapide et les vidéos suggérés sont affichées. La section \'Plus de vidéos\' dans l\'action rapide et la superposition de vidéos suggérés sont masquées. Masquer les vidéos associés + Les vidéos similaires sont affichés. + Les vidéos similaires sont masqués. + Masquer les vidéos similaires + "Ce paramètre limite le nombre maximum de mises en page pouvant être chargées sur l'écran du lecteur. + +Si la mise en page de l'écran du lecteur change en raison de modifications côté serveur, des mises en page non souhaitées peuvent être masquées sur l'écran du lecteur." Le bouton \"Remixer\" est affiché. Le bouton \"Remixer\" est masqué. Masquer le bouton \"Remixer\" @@ -796,6 +814,9 @@ Sous-titres" Le lien vers la vidéo complète est affiché. Le lien vers la vidéo complète est masqué. Masquer le lien de la vidéo complète + Le bouton \'fond vert\' est affiché. + Le bouton \'fond vert\' est masqué. + Masquer le bouton \'fond vert\' Les panneaux d\'information sont affichés. Les panneaux d\'information sont masqués. Masquer les panneaux d\'information @@ -829,9 +850,9 @@ Sous-titres" Le bouton \"Remixer\" est affiché. Le bouton \"Remixer\" est masqué. Masquer le bouton \"Remixer\" - Le son d\'enregistrement dans la Playlist est affiché. - Le son d\'enregistrement dans la Playlist est masqué. - Masquer le son du bouton \"Playlist\" + Le bouton \"Enregistrer la musique\" est affiché. + Le bouton \"Enregistrer la musique\" est masqué. + Masquer le bouton \"Enregistrer la musique\" Le bouton \"Suggestions de recherche\" est affiché. Le bouton \"Suggestions de recherche\" est masqué. Masquer le bouton \"Suggestions de recherche\" @@ -866,6 +887,9 @@ Effet secondaire : Les fiches officielles dans les résultats de recherche sont Les métadonnées de la musique sont affichés. Les métadonnées de la musique sont masqués. Masquer les métadonnées de la musique + Les stickers sont affichés. + Les stickers sont masqués. + Masquer les stickers Le bouton \"S\'abonner\" est affiché. Le bouton \"S\'abonner\" est masqué. Masquer le bouton \"S\'abonner\" @@ -938,15 +962,28 @@ La lecture automatique peut être modifiée dans les paramètres de YouTube : La section \"Transcription\" est affiché. La section \"Transcription\" est masqué. Masquer la section \"Transcription\" + "Masquer les vidéos avec l'étiquette À SUIVRE. + +Remarque : Activer ceci masque également le bouton \"M'avertir\"." + Masquer les vidéos À SUIVRE Les publicités vidéos sont affichées. Les publicités vidéos sont masquées. Masquer les publicités vidéo - Les vidéos supérieures à cette durée sont masqués. - Supérieur à la durée - Les vidéos inférieures à cette durée sont masqués. - Inférieur à la durée - Masque les vidéos inférieure ou supérieure à la durée.\n\nProblème connu : cela ne masque pas les vidéos similaires du lecteur, mais l\'horodatage sera masqué. - Masquer des vidéos selon la durée + "Les onglets Accueil / Abonnement et les résultats de la recherche sont filtrés pour masquer les vidéos dont le nombre de vues est inférieur ou supérieur à un nombre spécifié. + +Limitations : +- Les shorts ne peuvent pas être masqués. +- Les vidéos avec 0 vue ne sont pas filtrées." + À propos du filtrage par nombre de vues + Les vidéos de la page d\'accueil ne sont pas filtrés. + Les vidéos de la page d\'accueil sont filtrés. + Masquer les vidéos de la page d\'accueil par vues + Les résultats de recherche ne sont pas filtrés. + Les résultats de recherche sont filtrés. + Masquer les résultats de recherche par vues + Les vidéos dans l\'onglet Abonnement ne sont pas filtrés. + Les vidéos dans l\'onglet Abonnement sont filtrés. + Masquer les vidéos de l\'onglet Abonnement par vues Masque les vidéos recommandées ayant un nombre spécifié inférieur au nombre de vues.\n\nProblème connu : Les vidéos avec 0 vue ne sont pas filtrés. Masquer les vidéos recommandées par vues Les vidéos supérieurs à ce nombre de vues sont masqués. @@ -999,7 +1036,7 @@ La lecture automatique peut être modifiée dans les paramètres de YouTube : Les sous-textes sont affichés. Les sous-textes sont masqués. Masquer les sous-textes - L\'opacité du minilecteur doit être compris entre 0-100. Valeur réinitialisée par défaut. + L\'opacité du minilecteur doit être compris entre 0-100. Valeur d\'opacité entre 0-100, 0 étant transparent. Opacité du mini lecteur Original @@ -1040,13 +1077,18 @@ Appuyez longuement pour ouvrir les paramètres de la liste blanche. Le bouton \"Télécharger\" natif ouvre le téléchargeur de l\'appli. Le bouton \"Télécharger\" natif ouvre votre téléchargeur externe. Remplacer le bouton de téléchargement de la vidéo + YouTube Music est requis pour remplacer l\'action du bouton. Cliquez ici pour télécharger YouTube Music. + Prérequis + Le bouton \"YouTube Music\" ouvre l\'appli natif. + Le bouton \"YouTube Music\" ouvre RVX Music. + Remplacer le bouton \"YouTube Music\" Exclus Appliqué Normal Boutons d\'action Paramètres supplémentaires Animation / Retour d\'expérience - Filtre de durée + Bouton \"Télécharger\" Options expérimentales Restriction des images selon les régions Importer / Exporter sous forme de fichier @@ -1058,6 +1100,7 @@ Appuyez longuement pour ouvrir les paramètres de la liste blanche. Actions rapides Vidéo recommandée Étagères Shorts + Actions suggérées Outil utilisé Filtre du compteur de vues Masque ou affiche des éléments dans le menu du compte et dans l\'onglet \"Vous\". @@ -1088,13 +1131,15 @@ Appuyez longuement pour ouvrir les paramètres de la liste blanche. Interface Désactive ou active la vibration. Vibration + Remplace l\'action des boutons in-app. + Boutons d\'action Importer ou exporter les paramètres. Importer / Exporter les paramètres Change le style du lecteur minimisé de l\'application. Minilecteur Paramètres avancés - Masque ou affiche les éléments de la barre de navigation. - Barre de navigation + Masque ou affiche les éléments de la barre de navigation. + Barre de navigation Informations sur les patchs appliqués. Informations sur les patchs Masque ou affiche les boutons sur les vidéos. @@ -1123,13 +1168,14 @@ Appuyez longuement pour ouvrir les paramètres de la liste blanche. Vitesses et qualités vidéo Modifie les paramètres liés à l\'historique de visionnage. Historique de visionnage - La hauteur de l\'action rapide doit être comprise entre 0 et 32. Valeur réinitialisée par défaut. + La hauteur de l\'action rapide doit être comprise entre 0 et 32. Configure l\'espacement entre la barre de progression et le conteneur d\'actions rapides, entre 0 et 32. Hauteur de la barre de progression "Force le rejet de la réponse du codec AV1. Un codec différent sera appliqué après environ 20 secondes de mise en mémoire tampon." Rejeter la réponse du codec AV1 Le processus de rejet entraîne une mise en mémoire tampon d\'environ 20 secondes. + Décalage La modification de la vitesse de lecture est appliqué pour la vidéo en cours. La modification de vitesse de lecture est appliqué pour toutes les vidéos. Enreg. modif. de la vitesse de lecture @@ -1388,9 +1434,12 @@ Limitation : les \"Je n'aime pas\" ne seront pas affichées si vous n'êtes pas Cœur (Teinte) Masqué Animation lors du double appui - La marge en bas du panneau méta doit être entre 0-64, Valeur réinitialisée par défaut. - Définir l\'espacement entre la barre de progression et le panneau méta, entre 0-64. + La marge en bas du panneau méta doit être entre 0-64. + Configurer l\'espace de la barre de progression au panneau méta, entre 0-64. Marge en bas du panneau Meta + La hauteur en pourcentage doit être entre 0-100 (%). + Configure la hauteur en pourcentage de l\'espace vide à gauche lorsque la barre de navigation est cachée, entre 0 et 100 (%). + Hauteur en pourcentage de l\'espace vide Appuyez longuement sur l\'horodatage pour modifier l\'état de répétition des Shorts. Action de l\'horodatage appui long "Affiche la section du titre de la vidéo en plein écran. @@ -1411,7 +1460,7 @@ Info : Affic. message lors du passage Activer ce paramètre peut entraîner des problèmes de lecture vidéo. Tampon préchargé passé. - La valeur de la vitesse de lecture doit être comprise entre 0-8.0. Valeur réinitialisée par défaut. + La valeur de la vitesse de lecture doit être comprise entre 0-8.0. La valeur de vitesse de lecture doit être comprise entre 0-8.0. Valeur de \"Vitesse de lecture\" "Falsification de l'ancienne version du client @@ -1445,10 +1494,14 @@ Les hautes qualités peuvent être débloquées sur certaines vidéos qui requi "Activer ce paramètre peut améliorer l'autonomie de la batterie et résoudre les problèmes de lecture. AVC (H.264) a une résolution maximale de 1080p, et la lecture vidéo utilisera plus de données internet que le VP9 ou le AV1." - • Le menu \"Piste Audio\" est manquant. - • Le menu \"Piste Audio\" est manquant. + "• Le menu \"Piste Audio\" est manquant. +• Le volume stable n'es pas disponible." + "• Le menu \"Piste Audio\" est manquant. +• Le volume stable n'es pas disponible." "• Les films ou les vidéos payantes peuvent ne pas être lus. -• Les diffusions en direct commencent au début." +• Les diffusions en direct commencent au début. +• Les vidéos peuvent se terminer une seconde avant. +• Pas de codec audio opus." Effets inconnus de la falsification • Les vidéos peuvent ne pas être lus. Le client utilisé pour récupérer les données de lecture en direct est masqué dans \"Statistiques pour les nerds\". @@ -1471,7 +1524,7 @@ AVC (H.264) a une résolution maximale de 1080p, et la lecture vidéo utilisera Intensité des gestes La visibilité de l\'opacité du voile lors des gestes. Visibilité du voile lors des gestes - La zone glissable ne peut pas être supérieure à 50. Valeur réinitialisée par défaut. + La zone glissable ne peut pas être supérieure à 50. Pourcentage de la zone de l\'écran pouvant être glissée.\n\nNote : Cela affecte également la zone du double appui pour avancer/reculer dans la vidéo. Taille de la zone de gestes La taille du texte pendant le voile lors du geste. @@ -1494,6 +1547,10 @@ Note : Activer ceci masquera également les publicités vidéos." Si ce paramètre ne fait pas effet, essayer de passer en mode Incognito." Officiel + RVX Music + %s n\'est pas installé. Veuillez l’installer. + Nom du paquet de RVX Music installé. + Nom du paquet de RVX Music • L\'historique de visionnage est bloqué. "• Suit les paramètres de l'historique de visionnage du compte Google. • L'historique de visionnage peut ne pas fonctionner en raison d'un DNS ou d'un VPN." diff --git a/src/main/resources/youtube/translations/hu-rHU/missing_strings.xml b/src/main/resources/youtube/translations/hu-rHU/missing_strings.xml index 400746c71..9c08a6179 100644 --- a/src/main/resources/youtube/translations/hu-rHU/missing_strings.xml +++ b/src/main/resources/youtube/translations/hu-rHU/missing_strings.xml @@ -2,106 +2,38 @@ Don\'t show again Courses / Learning - Playables - "Auto switch mix playlists is enabled when autoplay is turned on. - -Autoplay can be changed in YouTube settings: -Settings → Autoplay → Autoplay next video" - Auto switch mix playlists is disabled. - Disable switch mix playlists - Enabling this feature will disable automatic switching to YouTube Mix when playing music while autoplay is turned on. - Default playback speed is enabled for music. - Disable playback speed for music - VP9 codec is enabled. - "VP9 codec is disabled. - -• Maximum resolution is 1080p. -• Video playback will use more internet data than VP9. -• To get HDR playback, HDR video still uses the VP9 codec." - Disable VP9 codec + Fountain animation is enabled above the Like button. + Fountain animation is disabled above the Like button. + Disable Like button animation Package name of your installed external downloader app, such as NewPipe or YTDLnis, on long press. Long press video downloader package name Displays the optimization dialog for GMSCore at each application startup. Show optimization dialog for GMSCore - Expandable shelves are shown. - Expandable shelves are hidden. - Hide expandable shelves - Surrounding a keyword/phrase with double-quotes will prevent partial matches of video titles and channel names.<br><br>For example,<br><b>\"ai\"</b> will hide the video: <b>How does AI work?</b><br>but will not hide: <b>What does fair use mean?</b> - Add quotes to use keyword: %s. - Keyword has conflicting declarations: %s. - Keyword is too short and requires quotes: %s. - "Floating buttons like 'Use this sound' are shown in the Shorts channel tab." - "Floating buttons like 'Use this sound' are hidden in the Shorts channel tab." - Location button is shown. - Location button is hidden. - Hide location button - Search suggestions button is shown. - Search suggestions button is hidden. - Hide search suggestions button - Shopping button is shown. - Shopping button is hidden. - Hide Shopping button - Trends button is shown. - Trends button is hidden. - Hide Trends button - Use template button is shown. - Use template button is hidden. - Hide Use template button - Use this sound button is shown. - Use this sound button is hidden. - Hide Use this sound button - "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. - -Limitations: -• Shorts cannot be hidden. -• Videos with 0 views are not filtered." - About view count filtering - Videos in home feed are not filtered. - Videos in home feed are filtered. - Hide home videos by views - Search results are not filtered. - Search results are filtered. - Hide search results by views - Videos in subscriptions feed are not filtered. - Videos in subscriptions feed are filtered. - Hide subscription videos by views + Green screen button is shown. + Green screen button is hidden. + Hide Green screen button + Save music button is shown. + Save music button is hidden. + Hide Save music button + Stickers are shown. + Stickers are hidden. + Hide stickers MMT Blue MMT Green + MMT Orange + MMT Pink + MMT Turquoise MMT Yellow Revancify Yellow Vanced Black Vanced Light Xisr Yellow - Spoof the streaming data to prevent playback issues. - Spoof streaming data + Suggested actions + Offset Adjust: Mark Start and End Time for segment Verify the Segment Edit the Segment Forward by Specified Time (Default: 150ms) Publish Created Segment Rewind by Specified Time (Default: 150ms) - Tap here to view your segments. - iOS video codec is AVC (H.264), VP9, or AV1. - "Enabling this might improve battery life and fix playback stuttering. - -AVC (H.264) has a maximum resolution of 1080p, and video playback will use more internet data than VP9 or AV1." - "• Movies or paid videos may not play. -• Livestreams start from the beginning." - Spoofing side effects - Client used to fetch streaming data is hidden in Stats for nerds. - Client used to fetch streaming data is shown in Stats for nerds. - Show in Stats for nerds - "Streaming data is not spoofed. Video playback may not work." - Streaming data is spoofed. - Spoof streaming data - Turning off this setting may cause video playback issues. - Create button is not switched with Notifications button. - "Create button is switched with Notifications button. - -Note: Enabling this also forcibly hides video ads." - "Disabling this might load more ads from the server. - -Also, ads will no longer be blocked in Shorts. - -If this setting do not take effect, try switching to Incognito mode." diff --git a/src/main/resources/youtube/translations/hu-rHU/strings.xml b/src/main/resources/youtube/translations/hu-rHU/strings.xml index 89f1a6d6b..9954bca6c 100644 --- a/src/main/resources/youtube/translations/hu-rHU/strings.xml +++ b/src/main/resources/youtube/translations/hu-rHU/strings.xml @@ -16,6 +16,7 @@ Ha engedélyezve van, a videó URL-je elküldésre kerül az API szerverre, de m Koppints ide, ha többet szeretnél megtudni a DeArrow-ról." A DeArrow-ról + Érvénytelen DeArrow API URL. A DeArrow bélyegkép cache végpont URL-je. DeArrow API végpont Nem jelenik meg üzenet, ha a DeArrow nem elérhető. @@ -83,17 +84,21 @@ Koppints ide, ha többet szeretnél megtudni a DeArrow-ról." Feliratkozások Felkapott Megnézem később - Érvénytelen kezdőlap, visszaállítás az eredetire. Kezdőlap megváltoztatása + A kiinduló lap csak egyszer változik. + "A kiinduló lap mindig változik. + +Korlátozás: Előfordulhat, hogy az eszköztár Vissza gombja nem működik." + Kiinduló lap megváltoztatása Az általános fejléc van engedélyezve. - Prémium fejléc van engedélyezve. + A prémium fejléc van engedélyezve. YouTube fejléc módosítása A szűrendő összetevő útvonal építő karakterláncok listája új sorral elválasztva Egyéni szűrő - Az egyedi szűrő ki van kapcsolva - Az egyedi szűrő engedélyezve van - Egyedi szűrők engedélyezése - Érvénytelen egyedi szűrő: %s + Az egyéni szűrő le van tiltva. + Az egyéni szűrő engedélyezett. + Egyéni szűrő engedélyezése + Érvénytelen egyéni szűrő: %s. A régi stílusú flyout menüt használja. Egyéni párbeszédpanelt használ. Egyedi lejátszási sebesség menü típusa @@ -128,12 +133,21 @@ Koppints ide, ha többet szeretnél megtudni a DeArrow-ról." Az automatikus lejátszó felugró panelek engedélyezve vannak. Az automatikus lejátszó felugró panelek le vannak tiltva. Lejátszó felugró panelek letiltása + "Az automatikus mix lejátszási listák engedélyezve vannak, ha az automatikus lejátszás be van kapcsolva. + +Az automatikus lejátszás a YouTube beállításaiban módosítható: +Beállítások → Automatikus lejátszás → Következő videó automatikus lejátszása" + Az automatikus mix lejátszási listák le vannak tiltva. + Mix lejátszási listák letiltása + A funkció engedélyezése letiltja az automatikus váltást a YouTube Mix szolgáltatásra, amikor zenét játszik le, miközben az automatikus lejátszás be van kapcsolva. Az alapértelmezett lejátszási sebesség engedélyezve van az élő közvetítésnél. Az alapértelmezett lejátszási sebesség le van tiltva élő közvetítésnél. Lejátszási sebesség letiltása élő közvetítésnél + Az alapértelmezett lejátszási sebesség engedélyezett zene lejátszásnál. "A zene alapértelmezett lejátszási sebessége le van tiltva. Korlátozás: Előfordulhat, hogy ez a beállítás nem vonatkozik azokra a videókra, amelyek nem tartalmazzák a „Hallgassa meg a YouTube Musicon” bannert." + Lejátszási sebesség zenéhez kiválasztás elrejtése Az interakciós panel engedélyezve. Az interakciós panel letiltva. Interakciós panel letiltása @@ -186,6 +200,13 @@ Megjegyzés: •Koppintás a görgetéshez. •Koppintás és tartás a szöveg kijelöléséhez." Videoleírás interakció letiltása + VP9 kodek engedélyezve van. + "A VP9 kodek le van tiltva. + +• A maximális felbontás 1080p. +• A videolejátszás több internetes adatot használ, mint a VP9. +• A HDR lejátszáshoz a HDR videó továbbra is a VP9 kodeket használja." + VP9 kodek letiltása A Cairo keresősáv le van tiltva. "A Cairo keresősáv engedélyezett. @@ -217,7 +238,7 @@ Mellékhatás: a Cairo stílus az értesítési pontokra is alkalmazódik."Színátmenetes betöltési képernyő engedélyezése A navigációs gombok közötti távolság normális. A navigációs gombok közötti távolság szűk. - Szűk navigációs gombok engedélyezése + Keskeny navigációs gombok engedélyezése Az alapértelmezett átirányítási rendet követi. Az URL átirányítások kikerülése. Közvetlen link megnyitások engedélyezése @@ -281,6 +302,7 @@ A 'Videoleírások kibővítése' nem működik, ha a beírt sztring nem egyezik A videoleírások automatikusan kibővülnek. Videoleírások kibővítése Szeretnéd folytatni? + Visszaállítás az alapértelmezett értékekre. Indítsa újra a rendszert a normál elrendezés betöltéséhez Frissítés és újraindítás A beállítások exportálása sikertelen. @@ -314,7 +336,7 @@ Töltsd le a(z) %2$s weboldalról." • Amikor egy videót elindítanak. • Amikor egy időbélyegre kattintanak a hozzászólásokban." Teljes képernyő erőltetése - A fiók menüben szűrendő nevek listája, új sorokkal elválasztva. + A fiók menüben szűrendő menüpontok listája, új sorokkal elválasztva. Fiók menü szűrő "Fiókmenü és az Ön lap elemeinek elrejtése. Előfordulhat, hogy egyes komponensek nincsenek elrejtve." @@ -422,14 +444,17 @@ Lejátszási listák A bővíthető vágások megjelennek. A bővíthető vágások el vannak rejtve. Bővíthető vágások elrejtése a videók alatt + A kinyitható polcok láthatóak. + A kinyitható polcok el vannak rejtve. + Kinyitható polcok elrejtése A Feliratok gomb megjelenik. A Feliratok gomb el van rejtve. Rejtsd el a hírfolyam feliratok gombját - Szűrendő lebegő menü neveinek listája, új sorral elválasztva. + Szűrendő lebegő menü neveinek listája, új sorokkal elválasztva. Hírfolyam lebegő menü szűrő A hírfolyam lebegő menü szűrő ki van kapcsolva. - A hírfolyam lebegő menü szűrő be van kapcsolva. - Hírfolyam lebegő menü szűrő bekapcsolása + A hírfolyam lebegő menü szűrő engedélyezve van. + Hírfolyam lebegő menü szűrő engedélyezése A hírfolyam keresősáv látható. A hírfolyam keresősáv elrejtve. Hírfolyam keresősáv elrejtése @@ -486,25 +511,34 @@ Korlátozás: előfordulhat, hogy a közösségi bejegyzés képe a teljes képe A kulcs koncepciók rész látható. A kulcs koncepciók rész elrejtve. Kulcs koncepciók rész elrejtése - "A Kezdőlap/Feliratkozások/Keresés eredményei a kulcsszóval megegyező tartalom elrejtésére vannak szűrve\n\nKorlátozások\n• Néhány Shorts lehet, hogy nem lesz elrejtve\n• Néhány UI elem lehet, hogy nem lesz elrejtve\n• Előfordulhat, hogy a kulcsszó keresése nem hoz eredményt" + "Kezdőlapi / Feliratkozási / Keresési eredmények szűrve vannak egyező kulcsszavak alapján. + +Korlátozások: +• A rövidfilmeket nem lehet elrejteni a csatornanév alapján. +• Előfordulhat, hogy egyes felhasználói felület-összetevők nincsenek elrejtve. +• Előfordulhat, hogy a kulcsszó keresése nem ad eredményt." A kulcsszó alapú szűrésről + Ha egy kulcsszót/kifejezést dupla idézőjelekkel vesz körül, akkor elkerülhető a videócímek és a csatornanevek részleges egyezése<br><br>Például:<br><b>\"ai\"</b> elrejti a videót: <b>Hogyan működik az AI?</b><br>de nem rejti el: <b>Mit jelent a fair use?</b> Teljes szóegyezések A kommentek nincsenek szűrve. A kommentek szűrve vannak. Kommentek elrejtése kulcsszavak alapján - A videók a kezdőlapon nincsenek szűrve - A videók a kezdőlapon kulcsszavak alapján szűrve + A videók a kezdőlapon nincsenek szűrve. + A videók a kezdőlapon szűrve vannak. Videók elrejtése a kezdőlapon kulcsszavak alapján - "Elrejtendő kulcsszavak és kifejezések, új sorokkal elválasztva.\n\nA szóközépen nagy betűt tartalmazó szavaknál a kis- és nagybetűknek a megfelelő helyen kell lennie (pl: iPhone, TikTok, LeBlanc)" + "Elrejteni kívánt kulcsszavak és kifejezések, új sorokkal elválasztva.\n\nA kulcsszavak lehetnek csatornanevek vagy bármilyen szöveg, amely a videók címében látható.\n\nA középen nagybetűs szavakat a kis- és nagybetűkkel együtt kell megadni (pl. iPhone, TikTok, LeBlanc)." Elrejtendő kulcsszavak A keresési eredmények nincsenek szűrve. A keresési eredmények szűrve vannak. Keresési eredmények elrejtése kulcsszavak alapján - A videók a feliratkozások lapon nincsenek szűrve - A videók a feliratkozások lapon kulcsszavak alapján szűrve - Videók elrejtése a feliratkozások lapon kulcsszavak alapján - A(z) %1$s kulcsszó elrejtené az összes videót. - Érvénytelen kulcsszó.\'%s\'nem használható szűrőként + A feliratkozott videók nincsenek szűrve. + A feliratkozott videók kulcsszavak alapján szűrve vannak. + Feliratkozott videók elrejtése kulcsszavak alapján + A kulcsszó elrejti az összes videót: %s. + Érvénytelen kulcsszó:\'%s. + Adjon hozzá idézőjeleket a következő kulcsszóhoz: %s. + A kulcsszónak ütköző deklarációi vannak: %s. + A keresőszó túl rövid, és idézőjeleket igényel: %s. A legutóbbi bejegyzések láthatóak. A legutóbbi bejegyzések el vannak rejtve. Legutóbbi bejegyzések elrejtése @@ -534,6 +568,9 @@ Korlátozás: előfordulhat, hogy a közösségi bejegyzés képe a teljes képe A filmek polcai láthatóak. A filmek polcai el vannak rejtve. Film polcok elrejtése + A navigációs sáv látható. + A navigációs sáv el van rejtve. + Navigációs sáv elrejtése A létrehozás gomb látható. A létrehozás gomb el van rejtve. Létrehozás gomb elrejtése @@ -549,11 +586,11 @@ Korlátozás: előfordulhat, hogy a közösségi bejegyzés képe a teljes képe Az értesítések gomb látható. Az értesítések gomb el van rejtve. Értesítések gomb elrejtése - A rövidítéseket gomb látható. - A rövidítéseket gomb el van rejtve. - Rövidítés gomb elrejtése - Az előfizetések gombja látható. - Az előfizetések gombja el van rejtve. + A Shorts gomb látható. + A Shorts gomb el van rejtve. + Shorts gomb elrejtése + Az előfizetések gomb látható. + Az előfizetések gomb el van rejtve. Feliratkozás gomb elrejtése Az \'Értesítsen\' gomb megjelenik. Az \'Értesítsen\' gomb el van rejtve. @@ -687,15 +724,20 @@ Korlátozás: előfordulhat, hogy a közösségi bejegyzés képe a teljes képe A gyorsműveletek megjelennek. A gyorsműveletek el vannak rejtve. Gyorsműveletek konténer elrejtése - "Az alábbi ajánlott videókat rejtse el: + "Elrejti a következő ajánlott videókat: -• Videókat, amelyeknek 'Csak tagsággal' címkéje van. -• Videókat, amelyek alatt olyan kifejezések találhatóak, mint a 'Mások is megnézték'. -• Azokat a videókat, amelyeket nem feliratkozott csatornákról töltöttek fel, és kevesebb, mint 1 000 megtekintésük van." +• Csak a tagok címkével ellátott videók. +• Olyan videók, amelyek alatt olyan kifejezések szerepelnek, mint „Mások is megnézték”." Ajánlott videók elrejtése A kapcsolódó videó átfedése látható. A kapcsolódó videó átfedése el van rejtve. Kapcsolódó videó átfedésének elrejtése + A kapcsolódó videók láthatóak. + A kapcsolódó videók el vannak rejtve. + Kapcsolódó videók elrejtése + "Ez a beállítás korlátozza a lejátszó képernyőjére betölthető elrendezések maximális számát. + +Ha a lejátszó képernyőjének elrendezése a szerveroldali változtatások miatt megváltozik, akkor esetleg a nem kívánt elrendezések elrejthetők a lejátszó képernyőjén." A remix gomb megjelenik A remix gomb el van rejtve Remix elrejtése @@ -731,7 +773,7 @@ Adatmegőrzés Feliratok" A szűrni kívánt YouTube beállítások menü neveinek listája, új sorokkal elválasztva. YouTube beállítások menü szűrő - Elrejt elemeket a YouTube beállítások menüben. + Elrejti a YouTube beállítások menü elemeit. YouTube beállítások menü elrejtése A megosztás gomb látható A megosztás gomb el van rejtve @@ -754,6 +796,8 @@ Feliratok" A nem tetszik gomb látható A nem tetszik gomb elrejtve Nem tetszik gomb elrejtése + "Az olyan lebegő gombok, mint a „Használja ezt a hangot”, a Shorts csatorna lapon láthatóak." + "Az olyan lebegő gombok, mint a „Használja ezt a hangot”, el vannak rejtve a Shorts csatorna lapon." Lebegő gomb elrejtése A teljes videólink címke megjelenik A teljes videólink címke el van rejtve @@ -770,6 +814,9 @@ Feliratok" Az élő csevegés fejléce látható.\n\nA fejlécben található Vissza gomb nem lesz elrejtve. Az élő csevegés fejléce el van rejtve.\n\nA fejlécben található Vissza gomb nem lesz elrejtve. Élő csevegés fejléc elrejtése + A hely gomb látható. + A hely gomb el van rejtve. + Hely gomb elrejtése A navigációs sáv megjelenik A navigációs sáv el van rejtve Navigációs sáv elrejtése @@ -788,9 +835,9 @@ Feliratok" A remix gomb megjelenik A remix gomb el van rejtve Remix gomb elrejtése - A hang mentése a lejátszási listára gomb megjelenik - A hang mentése a lejátszási listára gomb el van rejtve - Hang mentése a lejátszási listára gomb elrejtése + A keresési javaslatok gomb látható. + A keresési javaslatok gomb el van rejtve. + Keresési javaslatok gomb elrejtése A megosztás gomb látható A megosztás gomb el van rejtve Megosztás gomb elrejtése @@ -813,6 +860,9 @@ Korlát: A hivatalos fejlécek a keresési eredményekben el lesznek rejtve."A vásárlás gomb látható A vásárlás gomb el van rejtve Vásárlás gomb elrejtése + A vásárlás gomb látható. + A vásárlás gomb el van rejtve + Vásárlás gomb elrejtése A hang gomb megjelenik A hang gomb el van rejtve Hang gomb elrejtése @@ -831,6 +881,15 @@ Korlát: A hivatalos fejlécek a keresési eredményekben el lesznek rejtve."Az eszköztár látható. Az eszköztár el van rejtve. Eszköztár elrejtése + A Trend gomb látható. + A Trend gomb el van rejtve. + Trend gomb elrejtése + A sablon használata gomb látható. + A sablon használata gomb el van rejtve. + Sablon használata gomb elrejtése + Az ennek a zenének a használata gomb látható. + Az ennek a zenének a használata gomb el van rejtve. + Ennek a zenének a használata gomb elrejtése A cím megjelenik A cím el van rejtve Videó címének elrejtése @@ -885,15 +944,28 @@ Beállítások → Automatikus lejátszás → Következő videó automatikus le Az átirat rész megjelenik Az átirat rész el van rejtve Átirat rész elrejtése + "Videók elrejtése KÖZELGŐ címkével. + +Megjegyzés: Ha ezt engedélyezi, akkor az Értesíts gomb is el lesz rejtve." + KÖZELGŐ videó elrejtése A videó hirdetések láthatók A videó hirdetések el vannak rejtve Videó hirdetések elrejtése - Az ennél hosszabb videók el lesznek rejtve. - Hosszabb, mint - Az ennél rövidebb időtartamú videók el lesznek rejtve. - Rövidebb időtartamú, mint - Videók elrejtése rövidebb vagy hosszabb időtartam alapján.\n\nIsmert hiba: Nem fogja elrejteni a lejátszóban található kapcsolódó videókat, csak az időbélyegjét. - Videók elrejtése hossz alapján + "Kezdőlap / Feliratkozás / Keresés eredményei szűrve vannak, hogy elrejtse a meghatározott számnál kisebb vagy nagyobb nézettségű videókat. + +Korlátozások: +• A Shortokat nem lehet elrejteni. +• A 0 megtekintésű videók nincsenek kiszűrve." + Szűrés nézettség alapján névjegy + A videók a kezdőlapon nincsenek szűrve. + A videók a kezdőlapon szűrve vannak. + Videók elrejtése a kezdőlapon a nézettség alapján + A keresési eredmények nincsenek szűrve. + A keresési eredmények szűrve vannak. + Keresési eredmények elrejtése nézettség alapján + A feliratkozott videók nincsenek szűrve. + A feliratkozott videók szűrve vannak. + Feliratkozott videók elrejtése nézettség alapján Az ajánlott videók elrejtése, ha a megtekintések száma kevesebb a megadott számnál.\n\nIsmert probléma: a 0 megtekintésű videókat a rendszer nem szűri. Ajánlott videók elrejtése megtekintések alapján Az ennél nagyobb nézettségű videók el lesznek rejtve. @@ -902,7 +974,7 @@ Beállítások → Automatikus lejátszás → Következő videó automatikus le Kisebb a nézettsége, mint K -> 1 000\nM -> 1 000 000\nB -> 1 000 000 000\nviews -> megtekintések Adja meg nyelvi sablonját a videók alatt megjelenő nézetek számához a felhasználói felületen. Minden kulcs (a nyelvében levő betű/szó) -> érték (a kulcs jelentése) új sorban legyen. A kulcsok a \"->\" előtt helyezkednek el. Ha megváltoztatja az alkalmazás vagy a rendszer nyelvét, akkor vissza kell állítania ezt a beállítást.\n\nPéldák:\nAngol: 10K views = K -> 1000, views -> megtekintések\nSpanyol: 10 K vistas = K -> 1000, vistas -> megtekintések - Nézettség kulcsok + Kulcsok megtekintése A termékek megtekintése banner látható. A termékek megtekintése banner el van rejtve. Termékek megtekintése banner elrejtése @@ -929,11 +1001,11 @@ Beállítások → Automatikus lejátszás → Következő videó automatikus le Tartsa a fekvő módot Alap Dupla koppintás művelet letiltva. - "A dupla koppintás művelet engedélyezve. + "A dupla koppintás művelet engedélyezve van. -- Modern 1: A minimalizált videót nagyobb méretűre allítja. -- Modern 2, 3: A minimalizált videót bezárja." - Dupla koppintás művelet +• Koppintson duplán a kicsinyített videó nagyobb méretre való váltásához. +• Koppintson még egyszer duplán az eredeti méretre váltáshoz." + Dupla koppintás művelet engedélyezése A Fogd és vidd letiltva. A Fogd és vidd engedélyezve. Fogd és vidd engedélyezése @@ -987,13 +1059,18 @@ Tartsa nyomva a sebesség alaphelyzetbe állításához." Az eredeti letöltés gomb megnyitja az eredeti, beépített letöltőt. Az eredeti letöltés gomb megnyitja a külső letöltőt. Videó letöltési gomb felülbírálása + A YouTube Music szükséges a gombművelet felülbírálásához. Koppints ide a YouTube Music letöltéséhez. + Előfeltétel + A YouTube Music gomb az erdetit app-ot nyitja meg. + A YouTube Music gomb az RVX Music-ot indítja. + YouTube Music gomb felülbírálása Kizárva Befoglalt Normál Akció gombok További beállítások Animáció / Visszajelzés - Időtartam szűrő + Letöltés gomb Kísérleti funkciók Régiós kép korlátozások Importálás / Exportálás fájlként @@ -1027,7 +1104,7 @@ Tartsa nyomva a sebesség alaphelyzetbe állításához." Közösségi bejegyzések Komponensek elrejtése egyéni szűrőkkel. Egyéni szűrő - Komponensek elrejtése vagy megjelenítése a hírfolyam lebegő menüjében. + Komponensek elrejtése vagy megjelenítése a hírfolyam előugró menüjében. Felugró menü Hírfolyam Teljes képernyős móddal kapcsolatos elemek elrejtése vagy módosítása. @@ -1035,13 +1112,15 @@ Tartsa nyomva a sebesség alaphelyzetbe állításához." Általános Haptikus visszajelzés engedélyezése vagy letiltása. Haptikus visszajelzés + Felülbírálja az alkalmazáson belüli gombok kattintási műveletét. + Gombok felülbírálása Beállítások importálása vagy exportálása. Beállítások importálása / exportálása Módosítsa az alkalmazáson belüli minilejátszó stílusát. Minilejátszó Vegyes - Elrejtés vagy megjelenítés a navigációs sáv szakasz komponensei. - Navigációs gombok + Navigációs sáv komponenseinek láthatósága. + Navigációs sáv Információk az alkalmazott javításokról. Patch információ A videólejátszó gombok elrejtése vagy megjelenítése. @@ -1058,8 +1137,10 @@ Tartsa nyomva a sebesség alaphelyzetbe állításához." Komponensek elrejtése vagy megjelenítése a Rövid videók lejátszójában. Rövidfilm lejátszó Rövidfilmek + Az adatfolyam meghamisítása, hogy elkerülje a lejátszási problémákat. + Adatfolyam meghamisítása Húzásvezérlések - Elrejt vagy megváltoztat komponenseket az eszköztáron, mint például a keresősáv, eszköztárgombok és fejléc. + Elrejt vagy megváltoztat komponenseket az eszköztáron, mint például a keresősáv, eszköztár gombok és fejléc. Eszköztár Rejtsd el vagy mutasd a videóleírás komponenseit. Videóleírás @@ -1298,6 +1379,7 @@ Ide hosszan nyomva tartva megnyílik a YouTube beállítások." Visszaállítja a kihagyott szakaszok számlálóját? Ez <b>%s</b> <b>%s</b> szegmenst készítettél + Koppintson ide a szegmensek megtekintéséhez. Az ön felhasználóneve: <b>%s</b> Koppintson ide a felhasználónév megváltoztatásához A felhasználónév nem módosítható: Állapot: %1$d %2$s @@ -1333,6 +1415,9 @@ Ide hosszan nyomva tartva megnyílik a YouTube beállítások." A Meta panel alsó margójának 0-64 között kell lennie. Alapértelmezett értékekre visszaállítása. Állítsd be a keresősáv és a meta panel közötti távolságot 0-64 között. Meta panel alsó margó + A magasság százalékának 0-100 (%) között kell lennie. + Beállítja a navigációs sáv elrejtésekor megmaradó üres terület magasságának arányát 0 és 100 (%) között. + Az üres hely magasságának százaléka Nyomd meg és tartsd lenyomva az időbélyeget a Shortok ismétlés állapotának megváltoztatásához. Időbélyegző hosszú nyomás művelet "Megjeleníti a videócím szakaszt teljes képernyős módban. @@ -1366,9 +1451,9 @@ Info: 17.41.37 - Régi lejátszási lista polc visszállítása 18.05.40 - Régi megjegyzési szövegdoboz visszaállítása 18.17.43 - Régi előugró lejátszói ablak visszaállítása - 18.33.40 - Visszaállítás a régi Rövidítések műveletsávra + 18.33.40 - Régi Shorts művelet sáv visszaállítása 18.38.45 - Visszaállítja a régi alapértelmezett videó minőség viselkedést - 18.48.39 - Letiltja a \'nézetek\' és \'kedvelések\' valós idejű frissítését + 18.48.39 - Letiltja a \'Megtekintések\' és a \'Kedvelések\' valós idejű frissítését Hamis alkalmazásverzió Írja be a hamis alkalmazásverziót. Hamisított alkalmazásverzió célja @@ -1380,16 +1465,28 @@ Ez meg fogja változtatni az app működését és kinézetét és nem várt mel Ha kikapcsolja, akkor ajánlott törölni az app adatait, hogy elkerülje a UI hibákat." "Meghamisítja az eszköz méreteit annak érdekében, hogy feloldjon olyan jobb videóminőséget, amely esetleg nem érhető el az eszközön." Eszközméret hamisítása + Az iOS videokodek AVC (H.264), VP9 vagy AV1. Az iOS videokodek AVC (H.264). Kényszerített iOS AVC (H.264) - • Az audiosáv menü hiányzik. - • Az audiosáv menü hiányzik. + "Ennek engedélyezése javíthatja az akkumulátor élettartamát, és kijavíthatja a lejátszás akadozását.\n\nAz AVC (H.264) maximális felbontása 1080p, és a videolejátszás több internetadatot használ, mint a VP9 vagy az AV1." + "• Az audiosáv menü hiányzik." + "• Az audiosáv menü hiányzik." + "• Előfordulhat, hogy a filmeket vagy a fizetős videókat nem lehet lejátszani. +• Az élő közvetítések az elejétől kezdődnek." + Hamisítás mellékhatásai • A videó esetleg nem játszódik le. + Az adatfolyam lekérésére használt kliens a statisztikában kockáknak nem látható. + Az adatfolyam lekérésére használt kliens a statisztikában kockáknak látható. + Megjelenítés a statisztikában kockáknak + "Az adatfolyam nincs meghamisítva. Lehet, hogy a videó lejátszás nem működik." + Az adatfolyam hamisított. + Adatfolyam meghamisítása Android Android TV Android VR iOS Alapértelmezett kliens + A beállítás kikapcsolása videólejátszási problémákat okozhat. A csúsztatási mozdulatok le vannak tiltva a \'Képernyő lezárása\' módban. A csúsztatási mozdulatok engedélyezve vannak a \'Képernyő lezárása\' módban. A csúsztatási mozdulatok a \'Képernyő lezárása\' módban @@ -1411,8 +1508,19 @@ Megjegyzés: Ezzel a képernyőterület méretét is megváltoztatja, ahol érz • A készüléket esetleg újra kell indítani a beállítás változtatásának érvényesítéséhez. • Ha ezt a beállítást letiltja, több hirdetést tölt be a szerver oldalról. • Ha a videó hirdetések láthatóak akarja tenni, letiltja ezt a beállítást." - Létrehozás felcserélése az értesítésekkel + A Létrehozás gomb nincs felcserélve az Értesítések gombbal. + "A Létrehozás gomb megcserélése az Értesítések gombbal.\n\nMegjegyzés: Engedélyezés esetén a videó hirdetéseket is elrejti." + Létrehozás és értesítések gombok felcserélése + "Ennek kikapcsolása esetleg több reklámot tölt be a szerverről. + +Tovább, a reklámok nem lesznek tiltva a Shortokban. + +Ha ez a beállítás nem működik, váltson inkognító módra." Készlet + RVX Music + %s nincs telepítve. Kérlek telepítsd. + A telepített RVX Music csomag neve. + RVX Music csomag név • A megtekintési előzmények le vannak tiltva. "• Követi a Google-fiók megtekintési előzményeinek beállításait. • Előfordulhat, hogy a megtekintési előzmények nem működik a DNS vagy a VPN miatt." diff --git a/src/main/resources/youtube/translations/id-rID/missing_strings.xml b/src/main/resources/youtube/translations/id-rID/missing_strings.xml index 50d7e1f33..c8a03773a 100644 --- a/src/main/resources/youtube/translations/id-rID/missing_strings.xml +++ b/src/main/resources/youtube/translations/id-rID/missing_strings.xml @@ -1,6 +1,7 @@ Don\'t show again + Invalid DeArrow API URL. Still video captures The domain to fetch images from.\nNote: Only enter the domain name, i.e., without the \"https\:\/\/\" prefix. Alternative domain @@ -16,11 +17,14 @@ Live Movies Music - Playables Sports Watch later - Invalid start page, resetting to default. - Player overlay opacity must be between 0-100. Reset to default values. + Start page changes only once. + "Start page always changes. + +Limitation: Back button on the toolbar may not work." + Change start page type + Player overlay opacity must be between 0-100. Ambient mode is enabled in fullscreen. Ambient mode is disabled in fullscreen. Ambient mode is enabled. @@ -40,12 +44,15 @@ Limitation: This setting may not apply to videos that do not include the 'Listen Like and Dislike buttons will glow when mentioned. Like and Dislike buttons will not glow when mentioned. Disable Like and Dislike button glow + Fountain animation is enabled above the Like button. + Fountain animation is disabled above the Like button. + Disable Like button animation VP9 codec is enabled. "VP9 codec is disabled. • Maximum resolution is 1080p. • Video playback will use more internet data than VP9. -• To get HDR playback, HDR video still uses the VP9 codec." +• VP9 codec is still used for HDR video." Disable VP9 codec Cairo seekbar is disabled. "Cairo seekbar is enabled. @@ -71,6 +78,7 @@ Limitations: Navigation bar is translucent. Enable translucent navigation bar Do you wish to proceed? + Reset to default values. Search %s Package name of your installed external downloader app, such as YTDLnis. Playlist downloader package name @@ -117,6 +125,9 @@ Side effect: Community post images may be blocked in fullscreen." Hide live chat replay button Hide videos with less than 1,000 views from home feeds that have been uploaded from unsubscribed channels. Hide low views video + Navigation bar is shown. + Navigation bar is hidden. + Hide navigation bar Ambient mode menu is shown. Ambient mode menu is hidden. Hide Ambient mode menu @@ -129,12 +140,21 @@ Side effect: Community post images may be blocked in fullscreen." Promotion alert banner is shown. Promotion alert banner is hidden. Hide promotion alert banner + Related videos are shown. + Related videos are hidden. + Hide related videos + "This setting limits the maximum number of layouts that can be loaded on the player screen. + +If the layout of the player screen changes due to server-side changes, unintended layouts may be hidden on the player screen." Disabled comments button or with label \"0\" is shown. Disabled comments button or with label \"0\" is hidden. Hide disabled comments button "Floating buttons like 'Use this sound' are shown in the Shorts channel tab." "Floating buttons like 'Use this sound' are hidden in the Shorts channel tab." Hide floating button + Green screen button is shown. + Green screen button is hidden. + Hide Green screen button Live chat header is shown.\n\nBack button in header will not be hidden. Live chat header is hidden.\n\nBack button in header will not be hidden. Hide live chat header @@ -147,12 +167,18 @@ Side effect: Community post images may be blocked in fullscreen." Button background is shown. Button background is hidden. Hide Play & Pause button background + Save music button is shown. + Save music button is hidden. + Hide Save music button Search suggestions button is shown. Search suggestions button is hidden. Hide search suggestions button Shopping button is shown. Shopping button is hidden. Hide Shopping button + Stickers are shown. + Stickers are hidden. + Hide stickers Super Thanks button is shown. Super Thanks button is hidden. Hide Super Thanks button @@ -173,6 +199,10 @@ Side effect: Community post images may be blocked in fullscreen." Autoplay can be changed in YouTube settings: Settings → Autoplay → Autoplay next video" + "Hide videos with UPCOMING label. + +Note: Enabling this also hides the Notify me button." + Hide UPCOMING video "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. Limitations: @@ -195,6 +225,9 @@ Limitations: Afn Red MMT Blue MMT Green + MMT Orange + MMT Pink + MMT Turquoise MMT Yellow Revancify Yellow Vanced Black @@ -219,7 +252,7 @@ Limitations: Subtexts are shown. Subtexts are hidden. Hide subtexts - Miniplayer overlay opacity must be between 0-100. Reset to default values. + Miniplayer overlay opacity must be between 0-100. Opacity value between 0-100, where 0 is transparent. Overlay opacity Original @@ -243,15 +276,27 @@ Tap and hold to open whitelist setting dialog. Native video download button opens the native in-app downloader. Native video download button opens your external downloader. Override video download button + YouTube Music is required to override button action. Tap here to download YouTube Music. + Prerequisite + YouTube Music button opens the native app. + YouTube Music button opens the RVX Music. + Override YouTube Music button Animation / Feedback + Download button Image region restrictions + Suggested actions + Overrides the click action of in-app buttons. + Hook buttons Change the style of the in app minimized player. Miniplayer + Hide or show navigation bar section components. + Navigation bar Spoof the streaming data to prevent playback issues. Spoof streaming data Change settings related with watch history. Watch history - Quick actions top margin must be between 0-32. Reset to default values. + Quick actions top margin must be between 0-32. + Offset A toast will not be shown when changing the default playback speed. A toast will be shown when changing the default playback speed. Show a toast @@ -277,15 +322,21 @@ Tap and hold to open whitelist setting dialog. Heart (Tint) Hidden Double-tap animation - Meta panel bottom margin must be between 0-64. Reset to default values. + Meta panel bottom margin must be between 0-64. Configure the spacing from the seekbar to the meta panel, between 0-64. Meta panel bottom margin + Height percentage must be between 0-100 (%). + Configure the height percentage of the empty space left when the navigation bar is hidden, between 0 and 100 (%). + Height percentage of empty space Press and hold the timestamp to change the Shorts repeat status. Timestamp long press action Turning on this setting may cause video playback issues. - Speed overlay value must be between 0-8.0. Reset to default values. + Speed overlay value must be between 0-8.0. Version not spoofed Version spoofed + 18.33.40 - Restore old Shorts action bar + 18.38.45 - Restore old default video quality behavior + 18.48.39 - Disables views and likes from being updated in real time "App version will be spoofed to an older version of YouTube. This will change the appearance and features of the app, but unknown side effects may occur. @@ -297,10 +348,14 @@ If later turned off, it is recommended to clear the app data to prevent UI bugs. "Enabling this might improve battery life and fix playback stuttering. AVC (H.264) has a maximum resolution of 1080p, and video playback will use more internet data than VP9 or AV1." - • Audio track menu is missing. - • Audio track menu is missing. + "• Audio track menu is missing. +• Stable volume is not available." + "• Audio track menu is missing. +• Stable volume is not available." "• Movies or paid videos may not play. -• Livestreams start from the beginning." +• Livestreams start from the beginning. +• Videos may end 1 second early. +• No opus audio codec." Spoofing side effects • Video may not play. Client used to fetch streaming data is hidden in Stats for nerds. @@ -315,7 +370,7 @@ AVC (H.264) has a maximum resolution of 1080p, and video playback will use more iOS Default client Turning off this setting may cause video playback issues. - Swipeable area size cannot be more than 50. Reset to default value. + Swipeable area size cannot be more than 50. Percentage of swipeable screen area.\n\nNote: This will also change the size of the screen area for the double-tap-to-seek gesture. Swipe overlay screen size Create button is not switched with Notifications button. @@ -327,6 +382,10 @@ Note: Enabling this also forcibly hides video ads." Also, ads will no longer be blocked in Shorts. If this setting do not take effect, try switching to Incognito mode." + RVX Music + %s is not installed. Please install it. + Package name of installed RVX Music. + RVX Music package name • Watch history is blocked. "• Follows the watch history settings of Google account. • Watch history may not work due to DNS or VPN." diff --git a/src/main/resources/youtube/translations/id-rID/strings.xml b/src/main/resources/youtube/translations/id-rID/strings.xml index f819e91a4..9e9691424 100644 --- a/src/main/resources/youtube/translations/id-rID/strings.xml +++ b/src/main/resources/youtube/translations/id-rID/strings.xml @@ -691,9 +691,6 @@ Captions" Remix button is shown. Remix button is hidden. Hide remix button - Save sound to playlist is shown. - Save sound to playlist is hidden. - Hide save sound to playlist button Share button is shown. Share button is hidden. Hide share button @@ -780,12 +777,6 @@ Note: Video ads are shown. Video ads are hidden. Hide video ads - Videos with duration longer than this number will be hidden. - Longer than duration - Videos with duration shorter than this number will be hidden. - Shorter than duration - Hide videos with shorter than or longer than duration.\n\nKnown issue: It will not hide videos in the player related videos, instead it will hide the timestamp. - Hide videos based on duration Hide recommended videos with less than a specified number of views. Hide recommended videos by views Videos with views greater than this number will be hidden. @@ -836,7 +827,6 @@ Tap and hold to set playback speed to 1.0x." Normal Action buttons Additional settings - Duration filter Experimental Flags Import / Export as file Import / Export as text @@ -880,8 +870,6 @@ Tap and hold to set playback speed to 1.0x." Import or export settings. Import / Export settings Miscellaneous - Hide or show navigation bar section components. - Navigation buttons Information about applied patches. Patch information Hide or show buttons in videos. @@ -1177,9 +1165,6 @@ Limitation: Video title disappears when clicked." 17.41.37 - Restore old playlist shelf 18.05.40 - Restore old comment input box 18.17.43 - Restore old player flyout panel - 18.33.40 - Restore old shorts action bar - 18.38.45 - Restore old default video quality behavior - "18.48.39 - Disables 'views' and 'likes' from being updated in real time" Spoof app version target Type the spoof app version target. Edit spoof app version diff --git a/src/main/resources/youtube/translations/in/missing_strings.xml b/src/main/resources/youtube/translations/in/missing_strings.xml index 50d7e1f33..c8a03773a 100644 --- a/src/main/resources/youtube/translations/in/missing_strings.xml +++ b/src/main/resources/youtube/translations/in/missing_strings.xml @@ -1,6 +1,7 @@ Don\'t show again + Invalid DeArrow API URL. Still video captures The domain to fetch images from.\nNote: Only enter the domain name, i.e., without the \"https\:\/\/\" prefix. Alternative domain @@ -16,11 +17,14 @@ Live Movies Music - Playables Sports Watch later - Invalid start page, resetting to default. - Player overlay opacity must be between 0-100. Reset to default values. + Start page changes only once. + "Start page always changes. + +Limitation: Back button on the toolbar may not work." + Change start page type + Player overlay opacity must be between 0-100. Ambient mode is enabled in fullscreen. Ambient mode is disabled in fullscreen. Ambient mode is enabled. @@ -40,12 +44,15 @@ Limitation: This setting may not apply to videos that do not include the 'Listen Like and Dislike buttons will glow when mentioned. Like and Dislike buttons will not glow when mentioned. Disable Like and Dislike button glow + Fountain animation is enabled above the Like button. + Fountain animation is disabled above the Like button. + Disable Like button animation VP9 codec is enabled. "VP9 codec is disabled. • Maximum resolution is 1080p. • Video playback will use more internet data than VP9. -• To get HDR playback, HDR video still uses the VP9 codec." +• VP9 codec is still used for HDR video." Disable VP9 codec Cairo seekbar is disabled. "Cairo seekbar is enabled. @@ -71,6 +78,7 @@ Limitations: Navigation bar is translucent. Enable translucent navigation bar Do you wish to proceed? + Reset to default values. Search %s Package name of your installed external downloader app, such as YTDLnis. Playlist downloader package name @@ -117,6 +125,9 @@ Side effect: Community post images may be blocked in fullscreen." Hide live chat replay button Hide videos with less than 1,000 views from home feeds that have been uploaded from unsubscribed channels. Hide low views video + Navigation bar is shown. + Navigation bar is hidden. + Hide navigation bar Ambient mode menu is shown. Ambient mode menu is hidden. Hide Ambient mode menu @@ -129,12 +140,21 @@ Side effect: Community post images may be blocked in fullscreen." Promotion alert banner is shown. Promotion alert banner is hidden. Hide promotion alert banner + Related videos are shown. + Related videos are hidden. + Hide related videos + "This setting limits the maximum number of layouts that can be loaded on the player screen. + +If the layout of the player screen changes due to server-side changes, unintended layouts may be hidden on the player screen." Disabled comments button or with label \"0\" is shown. Disabled comments button or with label \"0\" is hidden. Hide disabled comments button "Floating buttons like 'Use this sound' are shown in the Shorts channel tab." "Floating buttons like 'Use this sound' are hidden in the Shorts channel tab." Hide floating button + Green screen button is shown. + Green screen button is hidden. + Hide Green screen button Live chat header is shown.\n\nBack button in header will not be hidden. Live chat header is hidden.\n\nBack button in header will not be hidden. Hide live chat header @@ -147,12 +167,18 @@ Side effect: Community post images may be blocked in fullscreen." Button background is shown. Button background is hidden. Hide Play & Pause button background + Save music button is shown. + Save music button is hidden. + Hide Save music button Search suggestions button is shown. Search suggestions button is hidden. Hide search suggestions button Shopping button is shown. Shopping button is hidden. Hide Shopping button + Stickers are shown. + Stickers are hidden. + Hide stickers Super Thanks button is shown. Super Thanks button is hidden. Hide Super Thanks button @@ -173,6 +199,10 @@ Side effect: Community post images may be blocked in fullscreen." Autoplay can be changed in YouTube settings: Settings → Autoplay → Autoplay next video" + "Hide videos with UPCOMING label. + +Note: Enabling this also hides the Notify me button." + Hide UPCOMING video "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. Limitations: @@ -195,6 +225,9 @@ Limitations: Afn Red MMT Blue MMT Green + MMT Orange + MMT Pink + MMT Turquoise MMT Yellow Revancify Yellow Vanced Black @@ -219,7 +252,7 @@ Limitations: Subtexts are shown. Subtexts are hidden. Hide subtexts - Miniplayer overlay opacity must be between 0-100. Reset to default values. + Miniplayer overlay opacity must be between 0-100. Opacity value between 0-100, where 0 is transparent. Overlay opacity Original @@ -243,15 +276,27 @@ Tap and hold to open whitelist setting dialog. Native video download button opens the native in-app downloader. Native video download button opens your external downloader. Override video download button + YouTube Music is required to override button action. Tap here to download YouTube Music. + Prerequisite + YouTube Music button opens the native app. + YouTube Music button opens the RVX Music. + Override YouTube Music button Animation / Feedback + Download button Image region restrictions + Suggested actions + Overrides the click action of in-app buttons. + Hook buttons Change the style of the in app minimized player. Miniplayer + Hide or show navigation bar section components. + Navigation bar Spoof the streaming data to prevent playback issues. Spoof streaming data Change settings related with watch history. Watch history - Quick actions top margin must be between 0-32. Reset to default values. + Quick actions top margin must be between 0-32. + Offset A toast will not be shown when changing the default playback speed. A toast will be shown when changing the default playback speed. Show a toast @@ -277,15 +322,21 @@ Tap and hold to open whitelist setting dialog. Heart (Tint) Hidden Double-tap animation - Meta panel bottom margin must be between 0-64. Reset to default values. + Meta panel bottom margin must be between 0-64. Configure the spacing from the seekbar to the meta panel, between 0-64. Meta panel bottom margin + Height percentage must be between 0-100 (%). + Configure the height percentage of the empty space left when the navigation bar is hidden, between 0 and 100 (%). + Height percentage of empty space Press and hold the timestamp to change the Shorts repeat status. Timestamp long press action Turning on this setting may cause video playback issues. - Speed overlay value must be between 0-8.0. Reset to default values. + Speed overlay value must be between 0-8.0. Version not spoofed Version spoofed + 18.33.40 - Restore old Shorts action bar + 18.38.45 - Restore old default video quality behavior + 18.48.39 - Disables views and likes from being updated in real time "App version will be spoofed to an older version of YouTube. This will change the appearance and features of the app, but unknown side effects may occur. @@ -297,10 +348,14 @@ If later turned off, it is recommended to clear the app data to prevent UI bugs. "Enabling this might improve battery life and fix playback stuttering. AVC (H.264) has a maximum resolution of 1080p, and video playback will use more internet data than VP9 or AV1." - • Audio track menu is missing. - • Audio track menu is missing. + "• Audio track menu is missing. +• Stable volume is not available." + "• Audio track menu is missing. +• Stable volume is not available." "• Movies or paid videos may not play. -• Livestreams start from the beginning." +• Livestreams start from the beginning. +• Videos may end 1 second early. +• No opus audio codec." Spoofing side effects • Video may not play. Client used to fetch streaming data is hidden in Stats for nerds. @@ -315,7 +370,7 @@ AVC (H.264) has a maximum resolution of 1080p, and video playback will use more iOS Default client Turning off this setting may cause video playback issues. - Swipeable area size cannot be more than 50. Reset to default value. + Swipeable area size cannot be more than 50. Percentage of swipeable screen area.\n\nNote: This will also change the size of the screen area for the double-tap-to-seek gesture. Swipe overlay screen size Create button is not switched with Notifications button. @@ -327,6 +382,10 @@ Note: Enabling this also forcibly hides video ads." Also, ads will no longer be blocked in Shorts. If this setting do not take effect, try switching to Incognito mode." + RVX Music + %s is not installed. Please install it. + Package name of installed RVX Music. + RVX Music package name • Watch history is blocked. "• Follows the watch history settings of Google account. • Watch history may not work due to DNS or VPN." diff --git a/src/main/resources/youtube/translations/in/strings.xml b/src/main/resources/youtube/translations/in/strings.xml index f819e91a4..9e9691424 100644 --- a/src/main/resources/youtube/translations/in/strings.xml +++ b/src/main/resources/youtube/translations/in/strings.xml @@ -691,9 +691,6 @@ Captions" Remix button is shown. Remix button is hidden. Hide remix button - Save sound to playlist is shown. - Save sound to playlist is hidden. - Hide save sound to playlist button Share button is shown. Share button is hidden. Hide share button @@ -780,12 +777,6 @@ Note: Video ads are shown. Video ads are hidden. Hide video ads - Videos with duration longer than this number will be hidden. - Longer than duration - Videos with duration shorter than this number will be hidden. - Shorter than duration - Hide videos with shorter than or longer than duration.\n\nKnown issue: It will not hide videos in the player related videos, instead it will hide the timestamp. - Hide videos based on duration Hide recommended videos with less than a specified number of views. Hide recommended videos by views Videos with views greater than this number will be hidden. @@ -836,7 +827,6 @@ Tap and hold to set playback speed to 1.0x." Normal Action buttons Additional settings - Duration filter Experimental Flags Import / Export as file Import / Export as text @@ -880,8 +870,6 @@ Tap and hold to set playback speed to 1.0x." Import or export settings. Import / Export settings Miscellaneous - Hide or show navigation bar section components. - Navigation buttons Information about applied patches. Patch information Hide or show buttons in videos. @@ -1177,9 +1165,6 @@ Limitation: Video title disappears when clicked." 17.41.37 - Restore old playlist shelf 18.05.40 - Restore old comment input box 18.17.43 - Restore old player flyout panel - 18.33.40 - Restore old shorts action bar - 18.38.45 - Restore old default video quality behavior - "18.48.39 - Disables 'views' and 'likes' from being updated in real time" Spoof app version target Type the spoof app version target. Edit spoof app version diff --git a/src/main/resources/youtube/translations/it-rIT/missing_strings.xml b/src/main/resources/youtube/translations/it-rIT/missing_strings.xml index cf0a420f0..e61c58590 100644 --- a/src/main/resources/youtube/translations/it-rIT/missing_strings.xml +++ b/src/main/resources/youtube/translations/it-rIT/missing_strings.xml @@ -2,19 +2,7 @@ Package name of your installed external downloader app, such as NewPipe or YTDLnis, on long press. Long press video downloader package name - "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. - -Limitations: -• Shorts cannot be hidden. -• Videos with 0 views are not filtered." - About view count filtering - Videos in home feed are not filtered. - Videos in home feed are filtered. - Hide home videos by views - Search results are not filtered. - Search results are filtered. - Hide search results by views - Videos in subscriptions feed are not filtered. - Videos in subscriptions feed are filtered. - Hide subscription videos by views + MMT Orange + MMT Pink + MMT Turquoise diff --git a/src/main/resources/youtube/translations/it-rIT/strings.xml b/src/main/resources/youtube/translations/it-rIT/strings.xml index b8e1057fe..50693c3ae 100644 --- a/src/main/resources/youtube/translations/it-rIT/strings.xml +++ b/src/main/resources/youtube/translations/it-rIT/strings.xml @@ -23,6 +23,7 @@ Se attivato, gli URL dei video verranno inviati al server API e non vengono invi Tocca qui per saperne di più su DeArrow." DeArrow + URL API DeArrow non valido. L\'URL dell\'endpoint della cache delle anteprime DeArrow. Endpoint API di DeArrow Notifica toast nascosta DeArrow non è disponibile. @@ -89,15 +90,18 @@ Tocca qui per saperne di più su DeArrow." Diretta Film Musica - Giochi interattivi Cerca Shorts Sport Iscrizioni Tendenze Guarda più tardi - Scheda iniziale non valida, ripristinata al valore predefinito. Cambia la scheda iniziale + La pagina iniziale cambia solo una volta. + "La pagina iniziale cambia sempre. + +Limitazione: Il pulsante indietro sulla barra degli strumenti potrebbe non funzionare." + Cambia il tipo di pagina iniziale L\'intestazione generica è abilitata. L\'intestazione Premium è abilitata. Cambia intestazione di YouTube @@ -194,6 +198,9 @@ Limitazione: Questa impostazione potrebbe non applicarsi ai video che non includ Le animazioni degli aggiornamenti in tempo reale dei contatori sono attivate Le animazioni degli aggiornamenti in tempo reale dei contatori sono disattivate Disattiva le animazioni degli aggiornamenti in tempo reale dei contatori + L\'animazione della fontana è abilitata sopra il pulsante mi piace. + L\'animazione della fontana è disabilitata sopra il pulsante mi piace. + Disabilita animazione pulsante Mi piace "Disabilita la funzione '2x>>' tenendo premuto. Nota: @@ -310,6 +317,7 @@ Scheda Tu → Visualizza canale → Menu → Impostazioni" Le descrizioni video vengono espanse automaticamente. Espandi descrizioni video Desideri procedere? + Ripristina ai valori predefiniti. Riavvia per caricare l\'interfaccia normalmente Aggiorna e riavvia Impossibile esportare le impostazioni @@ -577,6 +585,9 @@ Parole con lettere maiuscole all'interno devono essere inserite con il maiuscolo La sezione dei film è visibile. La sezione dei film è nascosta. Nascondi la sezione dei film + La barra di navigazione è mostrata. + La barra di navigazione è nascosta. + Nascondi la barra di navigazione Il pulsante Crea è visibile. Il pulsante Crea è nascosto. Nascondi il pulsante Crea @@ -738,6 +749,12 @@ Parole con lettere maiuscole all'interno devono essere inserite con il maiuscolo La sezione \'Più video\' nel contenitore delle azioni rapide e la sovrapposizione video correlato sono mostrate. La sezione \'Più video\' nel contenitore delle azioni rapide e la sovrapposizione video correlato sono nascoste. Nascondi sovrapposizione video correlato + I video correlati sono mostrati. + I video correlati sono nascosti. + Nascondi video correlati + "Questa impostazione limita il numero massimo di layout che possono essere caricati sulla schermata del player. + +Se il layout della schermata del player cambia a causa di modifiche lato server, i layout non intenzionali possono essere nascosti sullo schermo del giocatore." Il pulsante Remix è visibile. Il pulsante Remix è nascosto. Nascondi il pulsante Remix @@ -802,6 +819,9 @@ Sottotitoli" L\'etichetta del collegamento del video è mostrato. L\'etichetta del collegamento video è nascosta. Nascondi l\'etichetta completa del collegamento video + Il pulsante schermo verde è mostrato. + Il pulsante dello schermo verde è nascosto. + Nascondi pulsante schermo verde I pannelli informativi sono mostrati. I pannelli informativi sono nascosti. Nascondi i pannelli informativi @@ -835,9 +855,9 @@ Sottotitoli" Il pulsante Remix è mostrato. Il pulsante Remix è nascosto. Nascondi il pulsante Remix - Il pulsante Salva suono nella playlist è mostrato. - Il pulsante Salva suono nella playlist è nascosto. - Nascondi il pulsante Salva suono nella playlist + Il pulsante Salva musica è visibile. + Il pulsante Salva musica è nascosto. + Nascondi il pulsante Salva musica Il pulsante suggerimenti di ricerca è mostrato. Il pulsante suggerimenti di ricerca è nascosto. Nascondi il pulsante suggerimenti di ricerca @@ -870,6 +890,9 @@ Sottotitoli" L\'etichetta dei metadati è mostrata. L\'etichetta dei metadati è nascosta. Nascondi l\'etichetta dei metadati audio + Gli adesivi sono visibili. + Gli adesivi sono nascosti. + Nascondi adesivi Il pulsante d\'iscrizione è mostrato. Il pulsante d\'iscrizione è nascosto. Nascondi il pulsante d\'iscrizione @@ -945,15 +968,28 @@ Impostazioni → Riproduzione automatica → Riproduzione automatica del video s La sezione Trascrizione è visibile La sezione Trascrizione è nascosta Nascondi la sezione Trascrizione + "Nascondi i video con l'etichetta PROSSIMAMENTE. + +Nota: Abilitare questo nasconde anche il pulsante Notificami." + Nascondi i video PROSSIMAMENTE Gli annunci video sono visibili. Gli annunci video sono nascosti. Nascondi gli annunci video - I video con durata superiore a questo numero saranno nascosti. - Più lungo della durata - I video con durata inferiore a questo numero saranno nascosti. - Più breve della durata - Nasconde i video con più breve o più lunga durata.\n\nProblema noto: Non nasconderà i video nella sezione di video correlati, nella pagina di riproduzione dei video; invece ne nasconderà solo il timestamp. - Nasconde i video in base alla loro durata + "Home / iscrizione / I risultati della ricerca sono filtrati per nascondere i video con visualizzazioni inferiori o superiori a un numero specificato. + +Limitazioni: +• Gli short non possono essere nascosti. +• I video con 0 visualizzazioni non sono filtrati." + Informazioni sul filtro del conteggio delle visualizzazioni + I video della scheda Home non sono filtrati. + I video della scheda Home sono filtrati. + Nascondi video della scheda Home per visualizzazioni + I risultati di ricerca non sono filtrati. + I risultati della ricerca sono filtrati. + Nascondi i risultati della ricerca per visualizzazioni + I video della scheda iscrizioni feed non sono filtrati. + I video della scheda iscrizioni feed sono filtrati. + Nascondi i video della scheda iscrizioni per visualizzazioni Nascondi i video consigliati con meno di un numero specifico di visualizzazioni.\n\nProblema noto: I video con 0 visualizzazioni non vengono filtrati. Nascondi i video consigliati per il numero di visualizzazioni I video con più visualizzazioni di questo numero saranno nascosti. @@ -1057,13 +1093,18 @@ Tocca e tieni premuto per aprire la finestra delle impostazioni della whitelist. Il pulsante nativo per scaricare il video apre lo scaricatore nativo. Il pulsante nativo per scaricare il video apre il tuo scaricatore esterno. Sovrascrivi il pulsante per scaricare i video + YouTube music è necessario per sovrascrivere l\'azione del pulsante. Tocca qui per scaricare YouTube Music. + Prerequisito + Il pulsante YouTube Music apre l\'app nativa. + Il pulsante YouTube Music apre il RVX Music. + Sovrascrivi il pulsante YouTube Music Escluso Incluso Normale Pulsanti azione Impostazioni aggiuntive Animazione / Feedback - Filtro sulla durata + Pulsante download Opzioni sperimentali Restrizioni regionali delle immagini Importa / Esporta come file @@ -1075,6 +1116,7 @@ Tocca e tieni premuto per aprire la finestra delle impostazioni della whitelist. Azioni rapide Video consigliati Scaffali Shorts + Azioni suggerite Strumenti utilizzati Filtro sul numero di visualizzazioni Nascondi o mostra gli elementi nel menu account e nella scheda Tu. @@ -1105,13 +1147,15 @@ Tocca e tieni premuto per aprire la finestra delle impostazioni della whitelist. Generale Disabilita o abilita il feedback tattile. Feedback tattile + Sostituisce l\'azione del clic dei pulsanti in-app. + Pulsanti gancio Importa o esporta le impostazioni. Importa / Esporta impostazioni Cambia lo stile del riproduttore minimizzato nell\'app. Riproduttore minimizzato Varie - Nascondi o mostra i componenti della sezione della barra di navigazione. - Pulsanti di navigazione + Nascondi o mostra i componenti della sezione della barra di navigazione. + Barra di navigazione Informazioni sulle patch applicate. Informazioni patch Nascondi o mostra i pulsanti nel riproduttore video. @@ -1147,6 +1191,7 @@ Tocca e tieni premuto per aprire la finestra delle impostazioni della whitelist. Verrà applicato un codec diverso dopo circa 20 secondi di buffering." Rifiuta la risposta di codec AV1 software Il processo di Fallback provoca circa 20 secondi di buffering. + Sfalsamento Le modifiche della velocità di riproduzione si applicano solo al video corrente. Le modifiche della velocità di riproduzione si applicano a tutti i video. Ricorda le modifiche della velocità di riproduzione @@ -1414,6 +1459,9 @@ Limitazione: Non mi piace possono non apparire se l'utente non è registrato o i Il margine inferiore del pannello Meta deve essere compreso tra 0-64. Reimposta ai valori predefiniti. Configura la spaziatura dalla barra di ricerca al pannello meta, tra 0-64. Margine inferiore del pannello Meta + La percentuale di altezza deve essere compresa tra 0 e 100 (%). + Configura la percentuale di altezza dello spazio vuoto rimasto quando la barra di navigazione è nascosta, tra 0 e 100 (%). + Altezza percentuale di spazio vuoto Premi e tieni premuto il timestamp per cambiare lo stato di ripetizione degli Shorts. Azione pressione prolungata timestamp "Mostra la sezione del titolo del video a schermo intero. @@ -1468,8 +1516,8 @@ Se disattivata in seguito, si consiglia di cancellare i dati dell'app per evitar "Abilitando questo si potrebbe migliorare la durata della batteria e correggere i problemi di riproduzione. AVC (H. 264) ha una risoluzione massima di 1080p e la riproduzione video utilizzerà più dati internet rispetto a VP9 o AV1." - • il menu traccia audio è mancante. - • il menu traccia audio è mancante. + "• il menu traccia audio è mancante." + "• il menu traccia audio è mancante." "• I film o i video a pagamento potrebbero non essere riprodotti." Effetti collaterali del camuffamento • Il video potrebbe non essere riprodotto. @@ -1516,6 +1564,10 @@ Inoltre, gli annunci non saranno più bloccati negli Shorts. Se questa impostazione non ha effetto, prova a passare alla modalità Incognito." Inventario + RVX Music + %s Non è installato. Per favore installalo. + Nome del pacchetto di RVX Music installato. + Nome pacchetto RVX Music • La cronologia non funziona. "• Segue le impostazioni di cronologia dell'account Google. • La cronologia potrebbe non funzionare a causa di DNS o VPN." diff --git a/src/main/resources/youtube/translations/ja-rJP/missing_strings.xml b/src/main/resources/youtube/translations/ja-rJP/missing_strings.xml index d22a1f7f3..f82015e55 100644 --- a/src/main/resources/youtube/translations/ja-rJP/missing_strings.xml +++ b/src/main/resources/youtube/translations/ja-rJP/missing_strings.xml @@ -1,18 +1,6 @@ - "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. - -Limitations: -• Shorts cannot be hidden. -• Videos with 0 views are not filtered." - About view count filtering - Videos in home feed are not filtered. - Videos in home feed are filtered. - Hide home videos by views - Search results are not filtered. - Search results are filtered. - Hide search results by views - Videos in subscriptions feed are not filtered. - Videos in subscriptions feed are filtered. - Hide subscription videos by views + MMT Orange + MMT Pink + MMT Turquoise diff --git a/src/main/resources/youtube/translations/ja-rJP/strings.xml b/src/main/resources/youtube/translations/ja-rJP/strings.xml index d60f31915..cc0231e4a 100644 --- a/src/main/resources/youtube/translations/ja-rJP/strings.xml +++ b/src/main/resources/youtube/translations/ja-rJP/strings.xml @@ -21,6 +21,7 @@ DeArrowの詳細については、ここをタップしてください。" DeArrow + 無効な DeArrow API の URL です。 DeArrowサムネイルキャッシュエンドポイントのURL DeArrow API エンドポイント DeArrow が利用できない場合、トーストを表示します。 @@ -83,15 +84,18 @@ DeArrowの詳細については、ここをタップしてください。"ライブ 映画 音楽 - Playables 検索 ショート スポーツ 登録チャンネル トレンド 後で見る - 無効なスタートページです。デフォルトにリセットします。 起動時のページを変更 + 現在の設定: 起動時のページを一度のみ変更します。 + "現在の設定: 起動時のページを常に変更します。 + +注意: ツールバーの戻るボタンが機能しない場合があります。" + 「起動時のページを変更」の種類 左上のヘッダーを「Premium」に変更します。 左上のヘッダーを「Premium」に変更します。 YouTube ヘッダーを変更 @@ -128,7 +132,7 @@ DeArrowの詳細については、ここをタップしてください。"アンビエントモードを無効化 音声トラックが自動で選択されるのを無効化します。 -注意: この設定はショートには適用されません。 +注意: この設定はショート動画には適用されません。 音声トラックが自動で選択されるのを無効化します。 注意: この設定はショートには適用されません。 @@ -189,6 +193,9 @@ DeArrowの詳細については、ここをタップしてください。"高評価数と視聴回数の回転アニメーションを無効にします。 高評価数と視聴回数の回転アニメーションを無効にします。 数字の回転アニメーションを無効化 + 「高評価」ボタンの上部に表示されるアニメーションを無効化します。 + 「高評価」ボタンの上部に表示されるアニメーションを無効化します。 + 高評価ボタンのアニメーションを無効化 "画面を長押しして2倍速で再生する機能を無効にします。 注意: @@ -203,12 +210,8 @@ DeArrowの詳細については、ここをタップしてください。" 概要欄の操作を無効化 - VP9 コーデックを無効化します。 - -注意: \n -• 最大解像度は 1080p です。 -• 動画を再生する際には VP9 コーデックよりも多くの通信量を消費します。 -• HDR 再生を可能にするために、HDR 動画では引き続き VP9 コーデックが使用されます。 + VP9 コーデックを無効化します。\n\n注意: \n +• 最大解像度は 1080p です。\n• 動画を再生する際には VP9 コーデックよりも多くの通信量を消費します。\n • HDR 再生を可能にするために、HDR 動画では引き続き VP9 コーデックが使用されます。 "VP9 コーデックを無効化します。 注意: @@ -314,6 +317,7 @@ DeArrowの詳細については、ここをタップしてください。"概要欄を自動で展開します。 概要欄を自動で展開 続行しますか? + デフォルト値にリセットしました。 再起動してレイアウトを正常に読み込みます 再起動して更新 設定のエクスポートに失敗しました。 @@ -583,6 +587,9 @@ DeArrowの詳細については、ここをタップしてください。"有料の映画、テレビ番組を非表示にします。 有料の映画、テレビ番組を非表示にします。 映画欄を非表示 + ナビゲーションバー(ホーム、登録チャンネルなどのボタン)を非表示にします。 + ナビゲーションバー(ホーム、登録チャンネルなどのボタン)を非表示にします。 + ナビゲーションバーを非表示 「作成」ボタンを非表示にします。 「作成」ボタンを非表示にします。 作成ボタンを非表示 @@ -740,11 +747,17 @@ DeArrowの詳細については、ここをタップしてください。" +• 登録していないチャンネルからアップロードされた、再生回数が 1,000 回未満の動画" おすすめ動画を非表示 関連動画のオーバーレイを無効化します。 関連動画のオーバーレイを無効化します。 関連動画を非表示 + ホームフィードから関連動画を非表示にします。 + ホームフィードから関連動画を非表示にします。 + 関連動画を非表示 + "これを有効にすると、プレーヤー画面に読み込まれるレイアウトの最大数を制限します。 + +注意: サーバー側の変更によりプレーヤー画面のレイアウトが変更された場合、意図しないレイアウトがプレーヤー画面上から非表示になる可能性があります。" 「リミックス」ボタンを非表示にします。 「リミックス」ボタンを非表示にします。 「リミックス」ボタンを非表示 @@ -809,6 +822,9 @@ DeArrowの詳細については、ここをタップしてください。"フルの動画のリンクのラベルを非表示にします。 フルの動画のリンクのラベルを非表示にします。 フルの動画のリンクラベルを非表示 + プレーヤーの下部に表示される「グリーンスクリーン」ボタンを非表示にします。 + プレーヤーの下部に表示される「グリーンスクリーン」ボタンを非表示にします。 + グリーンスクリーンボタンを非表示 情報パネルを非表示にします。 情報パネルを非表示にします。 情報パネルを非表示 @@ -817,7 +833,7 @@ DeArrowの詳細については、ここをタップしてください。"「メンバーになる」ボタンを非表示 「高評価」ボタンを非表示にします。 「高評価」ボタンを非表示にします。 - 「高評価」ボタンを非表示 + 高評価ボタンを非表示 縦型のライブ配信のプレーヤー内で上部に表示されるチャンネル名などを非表示にします。\n\nヘッダーの戻るボタンは非表示になりません。 縦型のライブ配信のプレーヤー内で上部に表示されるチャンネル名などを非表示にします。\n\nヘッダーの戻るボタンは非表示になりません。 ライブチャットのヘッダーを非表示 @@ -842,9 +858,9 @@ DeArrowの詳細については、ここをタップしてください。"「リミックス」ボタンを非表示にします。 「リミックス」ボタンを非表示にします。 「リミックス」ボタンを非表示 - 音楽の「保存」ボタンを非表示にします。 - 音楽の「保存」ボタンを非表示にします。 - 「保存」ボタンを非表示 + 楽曲の「保存」ボタンを非表示にします。 + 楽曲の「保存」ボタンを非表示にします。 + 保存ボタンを非表示 検索候補のボタンを非表示にします。 検索候補のボタンを非表示にします。 検索候補のボタンを非表示 @@ -879,6 +895,9 @@ DeArrowの詳細については、ここをタップしてください。"プレーヤー下部に表示される楽曲のラベルを非表示にします。 プレーヤー下部に表示される楽曲のラベルを非表示にします。 楽曲のラベルを非表示 + ステッカーを非表示にします。 + ステッカーを非表示にします。 + ステッカーを非表示 「チャンネル登録」ボタンを非表示にします。 「チャンネル登録」ボタンを非表示にします。 「チャンネル登録」ボタンを非表示 @@ -948,15 +967,28 @@ DeArrowの詳細については、ここをタップしてください。"概要欄の文字起こしセクションを非表示にします。 概要欄の文字起こしセクションを非表示にします。 文字起こし欄を非表示 + "「プレミア公開」ラベルがついた動画を非表示にします。 + +注意: これを有効にすると「通知する」ボタンも非表示になります。" + プレミア公開動画を非表示 プレーヤー内の広告を非表示にします。 プレーヤー内の広告を非表示にします。 動画広告を非表示 - この数値より長い再生時間の動画を非表示にします。 - 再生時間が長い動画を非表示 - この数値より短い再生時間の動画を非表示にします。 - 再生時間が短い動画を非表示 - 設定した再生時間で動画を非表示にします。\n\n注意: 動画はプレーヤー関連の動画に表示されず、タイムスタンプを非表示にします。 - 動画を再生時間でフィルタリング + "ホーム / 登録チャンネル / 検索結果はフィルタリングされ、設定した値よりも少ない視聴回数の動画を非表示にします。 + +注意: +• ショート動画は非表示にできません。 +• 再生回数が 0 の動画はフィルタリングされません。" + 再生回数のフィルタリングについて + ホームフィード内の動画を再生回数でフィルタリングします。 + ホームフィード内の動画を再生回数でフィルタリングします。 + ホームフィードをフィルタリング + 検索結果を再生回数でフィルタリングします。 + 検索結果を再生回数でフィルタリングします。 + 検索結果をフィルタリング + 登録チャンネルの動画を再生回数でフィルタリングします。 + 登録チャンネルの動画を再生回数でフィルタリングします。 + 登録チャンネルをフィルタリング 設定した再生回数未満のおすすめ動画を非表示にします。 おすすめ動画を再生回数でフィルタリング この数値より多い再生回数の動画を非表示にします。 @@ -1056,14 +1088,19 @@ DeArrowの詳細については、ここをタップしてください。"プレイリストにダウンロードボタンを追加 「オフライン」ボタンで外部ダウンローダーを開きます。 「オフライン」ボタンで外部ダウンローダーを開きます。 - 「オフライン」ボタンを置き換え + 「オフライン」ボタンを置換 + ボタンを置換するには YouTube Music が必要です。ここをタップして YouTube Music をダウンロードします。 + 前提条件 + 「YouTube Music」ボタンで RVX Music を開けるようにします。 + 「YouTube Music」ボタンで RVX Music を開けるようにします。 + YouTube Music ボタンを置換 除外されています 適用されています 通常 プレーヤー下部(共有、クリップなど)のボタン その他の設定 アニメーション / フィードバック - 再生時間フィルター + ダウンロードボタン 実験的な機能 画像表示の地域制限 ファイルとしてインポート/エクスポート @@ -1075,6 +1112,7 @@ DeArrowの詳細については、ここをタップしてください。"クイック操作 おすすめ動画 ショート欄 + 推奨されるアクション 使用されたツール 再生回数フィルター 「アカウント」メニューと「マイページ」タブで要素を非表示または表示します。 @@ -1105,13 +1143,15 @@ DeArrowの詳細については、ここをタップしてください。"全般 触覚フィードバックを無効化または有効化します。 触覚フィードバック + YouTube 内の「YouTube Music」ボタンを置換します。 + ボタンをフック 設定をインポートまたはエクスポートします。 設定のインポート/エクスポート ミニプレーヤーのスタイルを変更します。 ミニプレーヤー その他 - ナビゲーションバーセクションのコンポーネントを非表示または表示します。 - ナビゲーションボタン + ナビゲーションバーセクションのコンポーネントを非表示または表示します。 + ナビゲーションバー 適用されたパッチに関する情報です。 パッチ情報 プレーヤー内のボタンを非表示または表示します。 @@ -1147,6 +1187,7 @@ DeArrowの詳細については、ここをタップしてください。" AV1 コーデックの応答を拒否 フォールバック処理で約20秒のバッファリングが発生します。 + オフセット 現在の設定: 再生速度の変更は現在の動画にのみ適用されます。 現在の設定: 再生速度の変更はすべての動画に適用されます。 再生速度の変更を保存 @@ -1167,15 +1208,15 @@ DeArrowの詳細については、ここをタップしてください。" 年齢制限ダイアログを削除 AV1 コーデックを VP9 コーデックに置き換えます。 - AV1 コーデックを置き換え + AV1 コーデックを置換 現在の設定: チャンネルのハンドル名が表示されます。 現在の設定: チャンネル名が表示されます。 ショートのチャンネル名を復元 現在の設定: プレーヤー左下のタイムスタンプをタップすると、残り時間が表示されます。 現在の設定: プレーヤー左下のタイムスタンプをタップすると、再生速度または画質のフライアウトメニューが開きます。 - タイムスタンプを置き換え + タイムスタンプを置換 「作成」ボタンを「設定」ボタンに置き換えます。 - 作成ボタンを置き換え + 「作成」ボタンを置換 "タップすると YouTube の設定が開きます。 長押しすると RVX 設定が開きます。" "タップすると RVX 設定が開きます。 @@ -1361,7 +1402,7 @@ DeArrowの詳細については、ここをタップしてください。"未送信のセグメントをスキップしました SponsorBlock は一時的に利用できません。 SponsorBlock は一時的に利用できません。(ステータス %d) - SponsorBlock は一時的に利用できません。 (API タイムアウト) + SponsorBlock は一時的に利用できません。(API がタイムアウトしました) 統計情報 統計は一時的に利用できません (API がダウンしています) 読み込み中... @@ -1414,6 +1455,9 @@ DeArrowの詳細については、ここをタップしてください。"メタパネルの下部の余白は 0 ~ 64 の間でなければなりません。デフォルト値にリセットします。 シークバーからメタパネルまでの間隔を 0 ~ 64 の間で設定できます。 メタパネルの下部の余白 + 高さは 0~100 (%) の間でなければなりません。 + ナビゲーションバーが非表示になっている際に残るスペースの高さを 0~100 (%) の間で設定します。 + スペースの高さを調整 タイムスタンプを長押しすると、ショートのリピート状態を変更できます。 タイムスタンプ長押し時の動作 "全画面表示時にタイトルを表示します。 @@ -1467,9 +1511,14 @@ DeArrowの詳細については、ここをタップしてください。""これを有効にすると、バッテリーの持ちが改善され、再生時のカクつきが修正される可能性があります。 注意: \n・AVC コーデック (H.264) の最大解像度は 1080p です。\n・動画の再生には VP9 や AV1 よりも多くの通信量を消費します。" - ・「音声トラック」メニューは表示されません。 - ・「音声トラック」メニューは表示されません。 - "• 映画や有料動画は再生できない場合があります。" + "・「音声トラック」メニューは表示されません。 +・「一定音量」は使用できません。" + "・「音声トラック」メニューは表示されません。 +• 「一定音量」は使用できません。" + "• 映画や有料動画は再生できない場合があります。 +•ライブは最初から再生されます。 +• 動画が 1 秒早く終了する場合があります。 +• Opus オーディオ コーデックは使用できません。" ストリーミングデータを偽装することによる副作用 • 動画が再生できない可能性があります。 統計情報に偽装したストリーミングデータを表示します。 @@ -1514,6 +1563,10 @@ DeArrowの詳細については、ここをタップしてください。" オリジナル + RVX Music + %s はインストールされていません。インストールしてください。 + インストールされている RVX Music のパッケージ名です。 + RVX Music のパッケージ名 • 再生履歴をブロックします。 "• Google アカウントの再生履歴の設定に従います。 • DNS や VPN が原因で再生履歴が動作しない可能性があります。" @@ -1522,7 +1575,7 @@ DeArrowの詳細については、ここをタップしてください。"タップして YouTube 再生履歴の管理画面を開きます。 すべての履歴を管理 オリジナル - ドメインを置き換え + ドメインを置換 再生履歴をブロック 再生履歴の種類 チャンネル「%1$s」を %2$s ホワイトリストに追加できませんでした。 diff --git a/src/main/resources/youtube/translations/ko-rKR/missing_strings.xml b/src/main/resources/youtube/translations/ko-rKR/missing_strings.xml index 86a5413fd..4995e20be 100644 --- a/src/main/resources/youtube/translations/ko-rKR/missing_strings.xml +++ b/src/main/resources/youtube/translations/ko-rKR/missing_strings.xml @@ -2,11 +2,8 @@ Package name of your installed external downloader app, such as NewPipe or YTDLnis, on long press. Long press video downloader package name - "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. - -Limitations: -• Shorts cannot be hidden. -• Videos with 0 views are not filtered." - About view count filtering + MMT Orange + MMT Pink + MMT Turquoise Xisr Yellow diff --git a/src/main/resources/youtube/translations/ko-rKR/strings.xml b/src/main/resources/youtube/translations/ko-rKR/strings.xml index 67ea04e2e..e3945082a 100644 --- a/src/main/resources/youtube/translations/ko-rKR/strings.xml +++ b/src/main/resources/youtube/translations/ko-rKR/strings.xml @@ -23,6 +23,7 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." DeArrow에 대한 정보 + 잘못된 DeArrow API URL 입니다. DeArrow 썸네일 캐시 엔드포인트 URL입니다. 이것이 무슨 역할을 하는지 모르는 경우에는 이 URL을 변경하지 마세요. DeArrow API 엔드포인트 DeArrow를 사용할 수 없을 때, 팝업 메시지를 표시하지 않습니다. @@ -85,15 +86,18 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 실시간 영화 음악 - 게임 룸 (Playables) 검색 Shorts 스포츠 구독 인기 급상승 나중에 볼 동영상 - 잘못된 앱 시작 페이지이므로 기본값으로 초기화합니다. 앱 시작 페이지 변경하기 + 앱 시작 페이지가 한 번만 변경됩니다. + "앱 시작 페이지가 항상 변경됩니다. + +알려진 문제점: 툴바에서 '뒤로 가기' 버튼이 작동되지 않을 수 있습니다." + 앱 시작 페이지 타입 변경하기 일반 헤더를 활성화합니다. Premium 헤더를 활성화합니다. YouTube 헤더 변경하기 @@ -106,11 +110,11 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 이전 메뉴 구성요소를 활성화합니다. 사용자 정의 다이얼로그를 활성화합니다. 사용자 정의 동영상 재생 속도 메뉴 타입 설정 - 사용자 정의 재생 속도는 %s 배속보다 작아야 하므로 기본값으로 초기화합니다. - 잘못된 재생 속도 값이므로 기본값으로 초기화합니다. + 사용자 정의 재생 속도는 %s 배속보다 작아야 합니다. + 잘못된 재생 속도 값입니다. 사용하고 싶은 동영상 재생 속도 값을 추가 또는 변경할 수 있습니다. 사용자 정의 동영상 재생 속도 편집하기 - 불투명도 값은 0-100 사이어야 하므로 기본값으로 초기화합니다. + 플레이어 오버레이 불투명도 값은 0-100 사이어야 합니다. 불투명도 값은 0-100 사이이며, 0은 투명입니다. 사용자 정의 플레이어 오버레이 불투명도 재생바 색상의 헥스 코드를 입력하세요. @@ -143,7 +147,7 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 설정 → 자동재생 → 다음 동영상 자동재생" 믹스 재생목록 자동전환을 비활성화합니다. 믹스 재생목록 전환 비활성화하기 - 이 설정을 활성화하면 자동재생이 켜져 있는 동안에 음악을 재생하면 YouTube 믹스 재생목록으로 자동전환되지 않습니다. + 이 설정을 활성화하면 자동재생이 켜져 있는 동안에 음악 동영상을 재생하면 YouTube 믹스 재생목록으로 자동전환되지 않습니다. 실시간 스트림에서 기본 동영상 재생 속도를 활성화합니다. 실시간 스트림에서 기본 동영상 재생 속도를 비활성화합니다. 실시간 스트림에서 기본 동영상 재생 속도 비활성화하기 @@ -190,6 +194,9 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 다음 롤링 넘버 애니메이션을 활성화합니다.\n• 조회수, 시청자 수 롤링 애니메이션 (플레이어 하단)\n• 좋아요 수, 조회수 롤링 애니메이션 (동영상 설명) 다음 롤링 넘버 애니메이션을 비활성화합니다.\n• 조회수, 시청자 수 롤링 애니메이션 (플레이어 하단)\n• 좋아요 수, 조회수 롤링 애니메이션 (동영상 설명) 롤링 넘버 애니메이션 비활성화하기 + 좋아요 버튼 상단에 표시되는 애니메이션을 활성화합니다. + 좋아요 버튼 상단에 표시되는 애니메이션을 비활성화합니다. + 좋아요 버튼 애니메이션 비활성화하기 "화면을 길게 눌러서 '2배속 >>'을 비활성화합니다. 알림: @@ -204,13 +211,11 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." • 눌러서 스크롤하기 • 길게 눌러서 텍스트 선택하기" 동영상 설명 상호 작용 비활성화하기 - VP9 코덱을 활성화합니다.\n\n• 예전에 업로드된 동영상에서 일부 화질 값들(480p+)이 누락되어 있거나 화질 메뉴를 선택할 수 없을 수 있습니다. + VP9 코덱을 활성화합니다.\n• 예전에 업로드된 동영상에서 일부 화질 값들이 제거되어 360p와 1080p(Premium 기능)만 선택할 수 있거나 화질 메뉴를 선택할 수 없을 수 있습니다. "VP9 코덱을 비활성화합니다. - -• 일부 동영상에서 누락되었던 화질 값들(480p+)이 표시될 수 있습이다. -• 최대 화질 값은 1080p으므로 초고화질 동영상을 재생할 수 없습니다. -• 동영상을 재생하면 VP9보다 더 많은 인터넷 데이터를 사용합니다. -• HDR 동영상을 재생할 수 없습니다." +• 재생 문제가 없는 계정이거나 iOS 클라이언트만 AV1 코덱을 지원하고 나머지 클라이언트는 VP9 코덱까지만 지원하기 때문에 iOS만 4K 동영상까지 재생될 수 있고, 나머지는 1080p까지 재생될 수 있습니다. +• AVC 코덱 동영상을 재생했을 경우에는 VP9보다 더 많은 데이터가 사용됩니다. +• HDR 동영상을 재생하기 위해 HDR 동영상에서는 VP9 또는 AV1 코덱이 사용됩니다." VP9 코덱 비활성화하기 Cairo 재생바를 비활성화합니다.\n• 그라데이션 색상 재생바 "Cairo 재생바를 활성화합니다. @@ -284,7 +289,7 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 스와이프 제스처로 볼륨 조절을 비활성화합니다. 스와이프 제스처로 볼륨 조절을 활성화합니다. 스와이프 제스처로 볼륨 조절 활성화하기 - dpi를 변경하여 일부 레이아웃을 태블릿 레이아웃으로 활성화합니다.\n이 설정을 활성화하면 다음 RVX 설정이 잠겨질 수 있습니다:\n• 커뮤니티 게시물 숨기기\n• 믹스 재생목록 숨기기\n• 빠른 작업 컨테이너 숨기기\n• 최신 동영상 버튼 숨기기\n• 관련 동영상 오버레이 숨기기 + dpi를 변경하여 일부 레이아웃을 태블릿 레이아웃으로 활성화합니다.\n\n이 설정을 활성화하면 다음 RVX 설정이 잠겨질 수 있습니다:\n• 커뮤니티 게시물 숨기기\n• 믹스 재생목록 숨기기\n• 최신 동영상 버튼 숨기기\n• 관련 동영상 오버레이 숨기기 태블릿 레이아웃 활성화하기 불투명 하단바를 활성화합니다. 반투명 하단바를 활성화합니다. @@ -311,6 +316,7 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 동영상 설명이 자동으로 펼쳐집니다. 동영상 설명 펼치기 계속하시겠습니까? + 기본값으로 초기화합니다. 레이아웃을 정상적으로 불러오기 위해 다시 시작합니다. 새로고침 및 다시 시작 설정을 내보낼 수 없습니다. @@ -458,10 +464,10 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 최종 화면 카드 숨기기 썸네일 하단에서 다음 정보들이 표시됩니다:\n동영상 설명, 챕터, 주요 순간, 스크립트,\n재생목록의 동영상, 이 동영상에 나온 제품 ... 썸네일 하단에서 다음 정보들이 숨겨집니다:\n동영상 설명, 챕터, 주요 순간, 스크립트,\n재생목록의 동영상, 이 동영상에 나온 제품 ... - 펼칠 수 있는 정보 숨기기 - 펼칠 수 있는 선반이 표시됩니다. - 펼칠 수 있는 선반이 숨겨집니다. - 펼칠 수 있는 선반 숨기기 + 펼쳐볼 수 있는 정보 숨기기 + 다음 선반이 표시됩니다:\n좋아하는 장르 선택 선반 + 다음 선반이 숨겨집니다:\n좋아하는 장르 선택 선반 + 펼쳐볼 수 있는 선반 숨기기 자막 버튼이 표시됩니다. 자막 버튼이 숨겨집니다. 피드 자막 버튼 숨기기 @@ -530,10 +536,10 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." "홈 / 구독 / 검색 결과가 필터링되어 키워드 구문과 일치하는 콘텐츠가 숨겨집니다. 알려진 문제점: -• 채널 이름으로 Shorts는 숨길 수 없습니다. +• 채널 이름으로 Shorts 동영상은 숨길 수 없습니다. • 일부 화면 구성요소는 숨겨지지 않을 수 있습니다. • 필터링 키워드를 검색하면 검색 결과가 표시되지 않을 수 있습니다." - 키워드 필터링 정보 + 키워드 필터링에 대한 정보 필터링할 키워드 및 구문을 큰따옴표로 묶으면 동영상 제목과 채널 이름이 부분적으로 일치하지 않도록 방지할 수 있습니다.<br><br>• 예를 들어, <b>\"ai\"</b>라는 키워드로 <b>AI 커리어 완벽 가이드</b>라는 동영상을 숨길 수 있지만, <b>생성형AI가 바꿔놓은 세계</b> 또는 <b>What does fair use mean?</b>라는 동영상은 숨길 수 없습니다.<br>• 그리고 구두점을 단어의 경계로 간주하기 때문에 <b>인공지능(AI)의 원리</b>라는 동영상은 숨길 수 있습니다. 큰따옴표는 다른 단어 내부의 하위 문자열만 무시합니다 (예: <b>fair</b>는 숨길 수 없지만, <b>f(ai)r</b>는 숨김). 전체 단어 일치시키기 댓글 섹션에서 키워드 필터를 비활성화합니다. @@ -587,6 +593,9 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 영화 선반이 표시됩니다. 영화 선반이 숨겨집니다. 영화 선반 숨기기 + 하단바가 표시됩니다. + 하단바가 숨겨집니다. + 하단바 숨기기 만들기 버튼이 표시됩니다. 만들기 버튼이 숨겨집니다. 만들기 버튼 숨기기 @@ -608,8 +617,8 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 구독 버튼이 표시됩니다. 구독 버튼이 숨겨집니다. 구독 버튼 숨기기 - 게시 예정 동영상 하단에서 \'알림 받기\' 버튼이 표시됩니다. - 게시 예정 동영상 하단에서 \'알림 받기\' 버튼이 숨겨집니다. + (게시) 예정 동영상 하단에서 \'알림 받기\' 버튼이 표시됩니다. + (게시) 예정 동영상 하단에서 \'알림 받기\' 버튼이 숨겨집니다. \'알림 받기\' 버튼 숨기기 유료 광고 포함 라벨이 표시됩니다. 유료 광고 포함 라벨이 숨겨집니다. @@ -747,6 +756,12 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 빠른 작업 컨테이너의 \'동영상 더보기\' 섹션과 관련 동영상 오버레이가 표시됩니다. 빠른 작업 컨테이너의 \'동영상 더보기\' 섹션과 관련 동영상 오버레이가 숨겨집니다. 관련 동영상 오버레이 숨기기 + 관련 동영상이 표시됩니다. + 관련 동영상이 숨겨집니다. + 관련 동영상 숨기기 + "이 설정은 플레이어 화면에서 로드할 수 있는 최대 레이아웃 수를 제한합니다. + +서버 측 변경으로 인해 플레이어 화면의 레이아웃이 변경되면 플레이어 화면에서 의도하지 않은 레이아웃이 숨겨질 수 있습니다." 리믹스 버튼이 표시됩니다. 리믹스 버튼이 숨겨집니다. 리믹스 버튼 숨기기 @@ -811,6 +826,9 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 동영상 링크 라벨이 표시됩니다. 동영상 링크 라벨이 숨겨집니다. FULL 또는 관련 동영상 링크 라벨 숨기기 + 그린 스크린 버튼이 표시됩니다. + 그린 스크린 버튼이 숨겨집니다. + 그린 스크린 버튼 숨기기 정보 패널이 표시됩니다. 정보 패널이 숨겨집니다. 정보 패널 숨기기 @@ -844,9 +862,9 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 리믹스 버튼이 표시됩니다. 리믹스 버튼이 숨겨집니다. 리믹스 버튼 숨기기 - (재생목록에) 음악 저장 버튼이 표시됩니다. - (재생목록에) 음악 저장 버튼이 숨겨집니다. - (재생목록에) 음악 저장 버튼 숨기기 + (재생목록에) 음악 저장 버튼이 표시됩니다. + (재생목록에) 음악 저장 버튼이 숨겨집니다. + (재생목록에) 음악 저장 버튼 숨기기 검색 추천 버튼이 표시됩니다. 검색 추천 버튼이 숨겨집니다. 검색 추천 버튼 숨기기 @@ -885,6 +903,9 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 메타데이터 라벨이 표시됩니다. 메타데이터 라벨이 숨겨집니다. 사운드 메타데이터 라벨 숨기기 + 스티커가 표시됩니다. + 스티커가 숨겨집니다. + 스티커 숨기기 구독 버튼이 표시됩니다. 구독 버튼이 숨겨집니다. 구독 버튼 숨기기 @@ -960,24 +981,28 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 스크립트 섹션이 표시됩니다. 스크립트 섹션이 숨겨집니다. 스크립트 섹션 숨기기 + "(게시) 예정 라벨이 있는 동영상이 숨겨집니다. + +알림: 이 설정을 활성화하면 '알림 받기' 버튼도 숨겨집니다." + (게시) 예정 동영상 숨기기 동영상 광고가 표시됩니다. 동영상 광고가 숨겨집니다. 동영상 광고 숨기기 - 입력한 숫자보다 재생시간이 긴 동영상을 숨길 수 있습니다. - 재생시간이 긴 동영상 숨기기 - 입력한 숫자보다 재생시간이 짧은 동영상을 숨길 수 있습니다. - 재생시간이 짧은 동영상 숨기기 - 재생시간이 짧거나 긴 동영상을 숨길 수 있습니다.\n\n알려진 문제점: 관련 동영상에서는 동영상이 숨겨지지 않고, 타임스탬프만 숨겨집니다. - 재생시간을 기준으로 동영상 숨기기 - 홈 피드 동영상이 필터링되지 않습니다. - 홈 피드 동영상이 필터링됩니다. - 조회수로 홈 피드 동영상 숨기기 - 검색 결과가 필터링되지 않습니다. - 검색 결과가 필터링됩니다. - 조회수로 검색 결과 숨기기 - 구독 피드 동영상이 필터링되지 않습니다. - 구독 피드 동영상이 필터링됩니다. - 조회수로 구독 피드 동영상 숨기기 + "홈 / 구독 / 검색 결과가 필터링되어 조회수가 지정한 수보다 적거나 많은 동영상이 숨겨집니다. + +알려진 문제점: +• Shorts 동영상은 숨길 수 없습니다. +• 실시간 스트림과 '조회수 없음' 동영상은 숨길 수 없습니다." + 조회수 필터링에 대한 정보 + 홈 피드에서 조회수 필터를 비활성화합니다. + 홈 피드에서 조회수 필터를 활성화합니다. + 홈 피드에서 조회수 필터 활성화하기 + 검색 결과에서 조회수 필터를 비활성화합니다. + 검색 결과에서 조회수 필터를 활성화합니다. + 검색 결과에서 조회수 필터 활성화하기 + 구독 피드에서 조회수 필터를 비활성화합니다. + 구독 피드에서 조회수 필터를 활성화합니다. + 구독 피드에서 조회수 필터 활성화하기 조회수가 높거나 낮은 추천 동영상을 숨길 수 있습니다.\n\n알려진 문제점: 실시간 스트림과 \'조회수 없음\' 동영상은 숨겨지지 않습니다. 조회수를 기준으로 동영상 숨기기 입력한 숫자보다 높은 조회수를 가진 동영상을 숨길 수 있습니다. @@ -1036,7 +1061,7 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 서브텍스트가 표시됩니다.\n• 왼쪽 하단에서 표시되는 \'유료 광고 포함\'과 같은 라벨 서브텍스트가 숨겨집니다.\n• 왼쪽 하단에서 표시되는 \'유료 광고 포함\'과 같은 라벨 서브텍스트 숨기기 - 불투명도 값은 0-100 사이어야 하므로 기본값으로 초기화합니다. + 미니 플레이어 오버레이 불투명도 값은 0-100 사이어야 합니다. 불투명도 값은 0-100 사이이며, 0은 투명입니다. 미니 플레이어 오버레이 불투명도 기기 기본값 사용 @@ -1077,13 +1102,18 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 동영상 오프라인 저장 버튼으로 기본 다운로더를 실행할 수 있습니다. (YouTube Premium 기능) 동영상 오프라인 저장 버튼으로 외부 다운로더를 실행할 수 있습니다. 동영상 오프라인 저장 버튼 재정의하기 + 버튼 동작을 재정의하려면 YouTube Music이 필요합니다. 여기를 눌러서 YouTube Music을 다운로드하세요. + 전제 조건 + YouTube Music 버튼으로 순정 YouTube Music을 실행할 수 있습니다. + YouTube Music 버튼으로 RVX Music을 실행할 수 있습니다. + YouTube Music 버튼 재정의하기 제외된 패치 포함된 패치 일반 액션 버튼 추가 설정 애니메이션 / 피드백 - 재생시간 필터 + 오프라인 저장 버튼 실험적인 기능 이미지 표시 제한 국가 파일로 가져오기 / 내보내기 @@ -1095,6 +1125,7 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 빠른 작업 추천 동영상 Shorts 선반 + 추천 동작 사용된 도구 조회수 필터 계정 메뉴와 내 페이지 탭에서 구성요소를 숨기거나 표시할 수 있습니다. @@ -1125,13 +1156,15 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 일반 진동 피드백을 활성화하거나 비활성화할 수 있습니다. 진동 피드백 + \'앱 내에 있는 버튼을 터치 시 실행 동작\'을 재정의할 수 있습니다. + 버튼 재정의 설정을 가져오거나 내보낼 수 있습니다. 설정 가져오기 / 내보내기 앱 내에서 최소화된 플레이어의 스타일을 변경할 수 있습니다. 미니 플레이어 기타 - 하단바 섹션에서 구성요소를 숨기거나 표시할 수 있습니다. - 하단바 버튼 + 하단바에서 섹션 구성요소를 숨기거나 표시할 수 있습니다. + 하단바 적용된 패치에 대한 정보입니다. 패치 정보 플레이어에서 버튼을 숨기거나 표시할 수 있습니다. @@ -1160,13 +1193,14 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 동영상 시청 기록과 관련된 설정을 변경할 수 있습니다. 시청 기록 - 빠른 작업 상단 여백 값은 0-32 사이어야 하므로 기본값으로 초기화합니다. + 빠른 작업 상단 여백 값은 0-32 사이어야 합니다. 재생바에서 빠른 작업 컨테이너까지의 간격을 0-32 사이로 지정할 수 있습니다. 빠른 작업 상단 여백 - "소프트웨어 AV1 코덱 응답을 강제로 거부합니다. + "AV1 코덱 응답을 강제로 거부합니다. 약 20초정도의 버퍼링 후에 다른 코덱으로 전환됩니다." - 소프트웨어 AV1 코덱 응답 거부하기 + AV1 코덱 응답 거부하기 Fallback 프로세스로 인해 약 20초정도의 버퍼링이 발생합니다. + 오프셋 동영상 재생 속도 값을 변경할 때마다 저장하지 않습니다. 동영상 재생 속도 값을 변경할 때마다 저장합니다. 동영상 재생 속도 저장 활성화하기 @@ -1183,10 +1217,10 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 모바일 네트워크 이용 시 기본 동영상 화질 값을 %s로 변경합니다. 동영상 화질을 설정할 수 없습니다. Wi-Fi 이용 시 기본 동영상 화질 값을 %s로 변경합니다. - "시청 경고 다이얼로그를 제거합니다.\n\n• 이 설정은 다이얼로그를 자동으로 허용하기만 하며 연령 제한(성인인증 절차)을 우회할 수 없습니다.\n• 성인인증이 필요한 동영상에서 인증을 하려 할 때, 휴대폰 번호가 필요하다고 알려주는 소형 팝업창(다이얼로그) 없이 바로 휴대폰 번호 인증 페이지가 표시됩니다." + "시청 경고 다이얼로그를 제거합니다.\n\n• 이 설정은 다이얼로그를 자동으로 허용하기만 하며 연령 제한(성인인증 절차)을 우회할 수 없습니다.\n• 즉, 성인인증이 필요한 동영상에서 인증을 하려 할 때, 휴대폰 번호가 필요하다고 알려주는 소형 팝업창(다이얼로그) 없이 바로 휴대폰 번호 인증 페이지가 표시됩니다." 시청 경고 다이얼로그 제거하기 - 소프트웨어 AV1 코덱을 VP9 코덱으로 변경합니다. - 소프트웨어 AV1 코덱 변경하기 + AV1 코덱을 VP9 코덱으로 변경합니다. + AV1 코덱 변경하기 채널 핸들(@채널 아이디)을 사용합니다. 채널 이름을 사용합니다. 채널 핸들 변경하기 @@ -1430,9 +1464,12 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 하트 (엷은색) 숨겨짐 두 번 누르기 애니메이션 - 메타 패널 하단 여백은 0-64 사이여야 하므로 기본값으로 초기화합니다. + 메타 패널 하단 여백은 0-64 사이여야 합니다. 재생바에서 메타 패널까지의 간격을 0-64 사이로 지정할 수 있습니다. 메타 패널 하단 여백 + 높이 비율은 0-100 사이어야 합니다 (백분율). + 하단바가 숨겨졌을 때, 남는 빈 공간의 높이 비율을 0에서 100사이로 지정할 수 있습니다 (백분율). + 빈 공간의 높이 비율 타임스탬프를 길게 눌러서 Shorts 반복 상태를 변경할 수 있습니다. 타임스탬프 길게 누르기 동작 "전체 화면에서 동영상 제목 섹션을 표시합니다. @@ -1452,7 +1489,7 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." 건너뛸 때, 팝업 메시지 표시하기 이 설정을 활성화하면 동영상 재생 문제가 발생할 수 있습니다. 미리 로드된 버퍼를 건너뛰었습니다. - 재생 속도 오버레이 값은 0-8.0 사이어야 하므로 기본값으로 초기화합니다. + 재생 속도 오버레이 값은 0-8.0 사이어야 합니다. 동영상 재생 속도 오버레이 값은 0-8.0 사이어야 합니다. 동영상 재생 속도 오버레이 값 "서버에 연결할 때 사용되는 앱 버전을 지정하여 앱 레이아웃을 변경합니다. @@ -1476,15 +1513,15 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요." "기기 크기 정보를 최대값으로 변경합니다. 높은 기기 크기 정보가 필요한 일부 동영상에서는 고화질 동영상 값이 잠금 해제될 수 있지만 모든 동영상에는 적용되지 않습니다." 기기 크기 정보 변경하기 - iOS 동영상 코덱을 AVC (H.264), VP9 또는 AV1으로 활성화합니다.\n\n• 예전에 업로드된 동영상을 재생했는데 VP9 코덱 응답을 받았을 경우, 일부 화질 값들(480p+)이 누락되어 있거나 화질 메뉴를 선택할 수 없을 수 있습니다. - iOS 동영상 코덱을 AVC (H.264)로 활성화합니다.\n\n• 일부 VP9 코덱 동영상에서 누락되었던 화질 값들(480p+)이 표시될 수 있습니다.\n• 최대 화질 값이 1080p이므로 초고화질 동영상을 재생할 수 없습니다.\n• HDR 동영상을 재생할 수 없습니다. + iOS 동영상 코덱을 AVC (H.264), VP9 또는 AV1으로 활성화합니다.\n\n• 예전에 업로드된 동영상을 재생했는데 VP9 코덱 응답을 받았을 경우, 일부 화질 값들이 제거되어 360p와 1080p(Premium 기능)만 선택할 수 있거나 화질 메뉴를 선택할 수 없을 수 있습니다. + iOS 동영상 코덱을 AVC (H.264)로 활성화합니다.\n\n• 일부 VP9 코덱 동영상에서 제거되었던 화질 값들이 표시될 수 있습니다.\n• 최대 화질 값이 1080p이므로 초고화질 동영상을 재생할 수 없습니다.\n• HDR 동영상을 재생할 수 없습니다 iOS AVC (H.264) 강제로 활성화하기 "이 설정을 활성화하면 배터리 수명이 향상되고 재생 끊김 현상이 해결될 수 있습니다. -AVC (H.264)의 최대 화질 값은 1080p이며 동영상을 재생하면 VP9 또는 AV1보다 더 많은 인터넷 데이터가 사용됩니다." - • 오디오 트랙 메뉴가 표시되지 않습니다.\n• 안정적인 볼륨 메뉴가 비활성화된 채로 잠겨있습니다. - • 오디오 트랙 메뉴가 표시되지 않습니다.\n• 안정적인 볼륨 메뉴가 비활성화된 채로 잠겨있습니다. - "• 영화 또는 유료 동영상이 재생되지 않을 수 있습니다.\n• 되감기가 가능한 실시간 스트림이 라이브 중인 시점이 아닌 처음부터 재생될 수 있습니다." +AVC (H.264)의 최대 화질 값은 1080p이며 동영상을 재생하면 VP9 또는 AV1보다 더 많은 데이터가 사용됩니다." + "• 오디오 트랙 메뉴가 표시되지 않습니다.\n• 안정적인 볼륨 메뉴가 비활성화된 채로 잠겨있습니다." + "• 오디오 트랙 메뉴가 표시되지 않습니다.\n• 안정적인 볼륨 메뉴가 비활성화된 채로 잠겨있습니다." + "• 영화 또는 유료 동영상이 재생되지 않을 수 있습니다.\n• 되감기가 가능한 실시간 스트림이 라이브 중인 시점이 아닌 처음부터 재생될 수 있습니다.\n• 동영상이 1초 일찍 종료될 수 있습니다.\n• OPUS 오디오 코덱이 지원되지 않습니다." 알려진 문제점 • 동영상이 재생되지 않을 수 있습니다. \'스트리밍 데이터를 가져오는 데 사용되는 클라이언트\'가 전문 통계에서 숨겨집니다. @@ -1507,7 +1544,7 @@ AVC (H.264)의 최대 화질 값은 1080p이며 동영상을 재생하면 VP9 스와이프 한계치 오버레이 투명도 값을 지정할 수 있습니다. (0–255) 오버레이 투명도 - 스와이프 영역 크기는 50 보다 클 수 없으므로 기본값으로 초기화합니다. + 스와이프 영역 크기는 50 보다 클 수 없습니다. 스와이프를 할 수 있는 화면 영역 크기를 지정할 수 있습니다. (백분율)\n\n알림: \'두 번 탭하여 탐색\' 제스처의 화면 영역 크기도 변경됩니다. 스와이프 오버레이 화면 크기 오버레이 텍스트 크기를 지정할 수 있습니다. @@ -1526,10 +1563,14 @@ AVC (H.264)의 최대 화질 값은 1080p이며 동영상을 재생하면 VP9 만들기 버튼과 알림 버튼 위치 교환하기 "이 설정을 비활성화하면 서버에서 더 많은 광고가 로드될 수 있습니다. -또한 Shorts에서 광고가 더 이상 차단되지 않습니다. +또한, Shorts에서 광고가 더 이상 숨겨지지 않습니다. 이 설정이 적용되지 않는 경우에는 시크릿 모드로 전환해 보세요." YouTube + RVX Music + %s 이 설치되어 있지 않습니다. 설치하세요. + 이 기기에 설치된 RVX Music 앱 패키지명을 설정하세요. + RVX Music 앱 패키지명 • 시청 기록이 차단됩니다. "• Google 계정의 시청 기록 설정을 따릅니다. • '광고 차단기', '광고 & 추적 차단 기능이 내장된 DNS 또는 VPN'으로 인해 시청 기록이 작동되지 않을 수 있습니다." diff --git a/src/main/resources/youtube/translations/pl-rPL/missing_strings.xml b/src/main/resources/youtube/translations/pl-rPL/missing_strings.xml new file mode 100644 index 000000000..36c253723 --- /dev/null +++ b/src/main/resources/youtube/translations/pl-rPL/missing_strings.xml @@ -0,0 +1,12 @@ + + + Save music button is shown. + Save music button is hidden. + Hide Save music button + Stickers are shown. + Stickers are hidden. + Hide stickers + MMT Orange + MMT Pink + MMT Turquoise + diff --git a/src/main/resources/youtube/translations/pl-rPL/strings.xml b/src/main/resources/youtube/translations/pl-rPL/strings.xml index 87a76d2f9..e86fe993b 100644 --- a/src/main/resources/youtube/translations/pl-rPL/strings.xml +++ b/src/main/resources/youtube/translations/pl-rPL/strings.xml @@ -21,6 +21,7 @@ Kontynuuj i wyłącz optymalizację baterii." Stuknij tutaj, aby dowiedzieć się więcej o DeArrow." DeArrow + Nieprawidłowy adres URL API DeArrow. Adres URL punktu końcowego do miniaturek DeArrow Punkt końcowy API DeArrow Ukryty @@ -83,15 +84,18 @@ Stuknij tutaj, aby dowiedzieć się więcej o DeArrow." Na żywo Filmy Muzyka - Pokój gier Wyszukiwanie Shortsy Sport Subskrypcje Na czasie Do obejrzenia - Nieprawidłowa strona startowa, zresetowano do domyślnej. Strona startowa + Strona główna zmienia się tylko raz + "Strona główna zawsze się zmienia + +Ograniczenie: Przycisk wstecz na pasku narzędzi może nie działać." + Działanie zmieniania strony głównej Domyślny Premium Zmień nagłówek YouTube @@ -104,11 +108,11 @@ Stuknij tutaj, aby dowiedzieć się więcej o DeArrow." Stary Własny Wygląd menu od prędkości odtwarzania - Niestandardowe prędkości muszą by mniejsze niż %sx. Przywrócono domyślne wartości. - Nieprawidłowe niestandardowe prędkości odtwarzania. Przywrócono domyślne wartości. + Niestandardowe prędkości muszą by mniejsze niż %sx. + Nieprawidłowe niestandardowe prędkości odtwarzania. Dodaj lub zmień dostępne prędkości odtwarzania Edytuj niestandardowe prędkości odtwarzania - Przezroczystość nakładki odtwarzacza musi wynosić między 0 a 100. Przywrócono domyślną wartość. + Przezroczystość nakładki odtwarzacza musi wynosić między 0 a 100. Wartość przezroczystości musi wynosić między 0 a 100, gdzie 0 oznacza przezroczystość Niestandardowa przezroczystość nakładki Wpisz kod hex koloru paska postępu filmu @@ -188,6 +192,9 @@ Ograniczenie: To ustawienie może nie działać dla filmów bez baneru 'Słuchaj Włączone Wyłączone Animacje liczb + Włączona + Wyłączona + Animacja przycisku polubienia "Wyłącz 'Odtwarzam 2x szybciej' podczas przytrzymywania. Notki: @@ -207,7 +214,7 @@ Notki: • Maksymalną rozdzielczością filmów jest 1080p • Odtwarzanie filmów wykorzystuje więcej danych internetowych niż VP9 -• Aby filmy w HDR się odtwarzały, będą one nadal używać kodeka VP9" +• Kodek VP9 jest używany do filmów z HDR" Wyłącz kodek VP9 Wyłączony "Włączony @@ -306,6 +313,7 @@ Opcja rozwijania opisu filmu może nie działać, jeśli wprowadzony ciąg znak Automatycznie Otwieraj opisy filmów Czy chcesz kontynuować? + Przywrócono domyślne wartości. Uruchom ponownie, aby wczytać poprawnie układ aplikacji Odśwież i uruchom ponownie Nie udało się wyeksportować ustawień. @@ -579,6 +587,9 @@ Słowa z wielkimi literami w środku muszą być wpisane z odpowiednią wielkoś Widoczne Ukryte Półki z filmami kinowymi + Widoczny + Ukryty + Pasek nawigacji Widoczny Ukryty Przycisk od przesyłania @@ -740,6 +751,12 @@ Słowa z wielkimi literami w środku muszą być wpisane z odpowiednią wielkoś Widoczne Ukryte Rekomendacje YouTube na końcu filmu + Widoczne + Ukryte + Powiązane filmy + "Ustawienie te ogranicza maksymalną ilość układów aplikacji, jakie mogą być załadowane na ekranie odtwarzacza. + +Jeśli układ ekranu odtwarzacza zmieni się w skutek zmian po stronie serwera, niepożądane układy mogą być ukryte na ekranie odtwarzacza." Widoczny Ukryty Przycisk od remiksowania @@ -804,6 +821,9 @@ Napisy" Widoczne Ukryte Etykiety z linkami do całych filmów + Widoczny + Ukryty + Przycisk od greenscreena Widoczne Ukryte Panele z informacjami @@ -837,9 +857,6 @@ Napisy" Widoczny Ukryty Przycisk od remiksowania - Widoczny - Ukryty - Przycisk od zapisywania dźwięku do playlisty Widoczny Ukryty Przycisk od sugestii wyszukiwań @@ -946,24 +963,28 @@ Autoodtwarzanie można zmienić w ustawieniach YouTube: Widoczne Ukryte Transkrypcje + "Ukryj filmy z etykietą WKRÓTCE. + +Uwaga: Włączenie tego ustawienia ukryje też przycisk 'Powiadom mnie'." + Ukryj zaplanowane filmy Widoczne Ukryte - Na stronie głównej Reklamy w filmach - Włączone + "Strona główna / subskrypcje / wyniki wyszukiwania są filtrowane, by ukrywać filmy z ilością wyświetleń mniejszą bądź większą od określonej liczby. + +Ograniczenia: +• Shortsy nie mogą zostać ukryte +• Filmy z 0 wyświetleń nie są filtrowane" + O filtrowaniu filmów po wyświetleniach Wyłączone - Włączone + Włączone + Na stronie głównej Wyłączone + Włączone W wynikach wyszukiwania - Włączone Wyłączone + Włączone Na stronie subskrypcji - Filmy o czasie trwania większym od tej liczby zostaną ukryte - Dłuższe od czasu trwania - Filmy o czasie trwania mniejszym od tej liczby zostaną ukryte - Krótsze od czasu trwania - Ukrywa filmy krótsze lub dłuższe od czasu trwania.\n\nZnany problem: Nie ukrywa filmów w rekomendacjach YouTube na końcach filmów - zamiast tego ukrywa czas. - Ukryj filmy na podstawie czasu trwania Ukrywa rekomendowane filmy, które mają mniejszą ilość wyświetleń niż zadeklarowana.\n\nZnany problem: Filmy z zerem wyświetleń nie są filtrowane. Ukryj rekomendowane filmy według ilości wyświetleń Filmy z wyświetleniami większymi niż ta liczba zostaną ukryte @@ -971,12 +992,6 @@ Autoodtwarzanie można zmienić w ustawieniach YouTube: Filmy z wyświetleniami mniejszymi niż ta liczba zostaną ukryte Mniej popularne tys. -> 1 000\nmln -> 1 000 000\nmld - > 1 000 000 000\n wyświetleń-> views - O filtrowaniu filmów po wyświetleniach - "Strona główna / subskrypcje / wyniki wyszukiwania są filtrowane, by ukrywać filmy z ilością wyświetleń mniejszą bądź większą od określonej liczby. - -Ograniczenia: -• Shortsy nie mogą zostać ukryte -• Filmy z 0 wyświetleń nie są filtrowane" Określ swój szablon językowy dla liczby wyświetleń pod każdym filmem w interfejsie użytkownika. Każdy klucz (litera/słowo w twoim języku) - > wartość (znaczenie klucza) musi znajdować się w nowej linii. Klucze muszą znajdować się przed znakiem \"->\". Jeśli zmienisz język aplikacji, musisz zresetować to ustawienie.\n\nPrzykłady:\nAngielski: 10K views = K -> 1000, views -> views\nPolski: 10 tys. wyświetleń = tys -> 1000, wyświetleń -> views Wyświetl klucze Widoczne @@ -1029,7 +1044,7 @@ Ograniczenia: Widoczne Ukryte Podteksty - Przezroczystość nakładki miniodtwarzacza musi wynosić między 0 a 100. Przywrócono domyślną wartość. + Przezroczystość nakładki miniodtwarzacza musi wynosić między 0 a 100. Wartość przezroczystości musi wynosić między 0 a 100, gdzie 0 oznacza przezroczystość Przezroczystość nakładki Oryginalny @@ -1070,13 +1085,19 @@ Stuknij i przytrzymaj, by otworzyć okno ustawień białej listy. Natywne pobieranie Zewnętrzna aplikacja Metoda pobierania filmów + YouTube Music jest wymagane do zmiany tego ustawienia. +Stuknij tutaj, by pobrać YouTube Music. + Wymaganie wstępne + YouTube Music + RVX Music + Aplikacja otwierana przyciskiem do YouTube Music Wykluczone Zawarte Normalna Przyciski akcji Dodatkowe ustawienia Animacje / Przesyłanie opinii - Filtrowanie według czasu trwania + Przycisk od pobierania Ustawienia Eksperymentalne Ograniczenia regionu dla obrazów Zaimportuj / Wyeksportuj jako plik @@ -1088,6 +1109,7 @@ Stuknij i przytrzymaj, by otworzyć okno ustawień białej listy. Pod paskiem postępu filmu Rekomendowane filmy Półki z Shortsami + Sugerowane akcje Użyte narzędzie Filtr ilości wyświetleń Ukryj bądź pokaż elementy w menu konta i zakładki Ty @@ -1118,13 +1140,15 @@ Stuknij i przytrzymaj, by otworzyć okno ustawień białej listy. Ogólne Wyłącz lub włącz wibracje Wibracje + Nadpisuje działanie przycisków w aplikacji + Zmień działanie przycisków Ustawienia importu oraz eksportu Zaimportuj / Wyeksportuj ustawienia Zmień styl miniodtwarzacza w aplikacji Miniodtwarzacz Pozostałe - Ukryj lub pokazuj przyciski nawigacji - Przyciski nawigacji + Ukryj lub pokazuj przyciski nawigacji + Pasek nawigacji Informacje na temat zastosowanych łatek. Informacje o łatkach Ukryj lub pokazuj przyciski w odtwarzaczu @@ -1153,13 +1177,14 @@ Stuknij i przytrzymaj, by otworzyć okno ustawień białej listy. Filmy Zmień ustawienia związane z historią oglądania Historia oglądania - Górny margines przycisków na dole odtwarzacza musi wynosić między 0 a 32. Przywrócono domyślną wartość. + Górny margines przycisków na dole odtwarzacza musi wynosić między 0 a 32. Skonfiguruj odstęp od paska postępu filmu do kontenera szybkich akcji, w zakresie od 0 do 32. Górny margines przycisków na dole odtwarzacza "Odrzucaj kodek AV1 programu. Po około 20 sekundach ładowania kodek zostanie zmieniony." Odrzucaj kodek AV1 programu Ten sposób powoduje około 20 sekund ładowania. + Przesunięcie Zmiany prędkości odtwarzania dotyczą tylko bieżącego filmu Zmiany prędkości odtwarzania dotyczą wszystkich filmów Zapamiętuj zmiany prędkości odtwarzania @@ -1424,9 +1449,12 @@ Ograniczenie: Liczba łapek w dół może nie być widoczna, gdy użytkownik nie Serce (jaśniejsze) Ukryta Animacja po dwukrotnym kliknięciu - Dolny margines panelu meta musi wynosić między 0 a 64. Przywrócono domyślne wartości. + Dolny margines panelu meta musi wynosić między 0 a 64. Skonfiguruj odstęp od paska postępu filmu do panelu meta, w zakresie od 0 do 64. Dolny margines panelu meta + Wysokość musi wynosić od 0 do 100 (%). + Zmienia wysokość pustej przestrzeni po ukryciu paska nawigacyjnego, od 0 do 100 (%) + Wysokość pustego miejsca (procentowa) Naciśnij i przytrzymaj czas, aby zmienić status powtarzania Shortsów Akcja po długim naciśnięciu czasu "Tytuły filmów w trybie pełnoekranowym są widoczne. @@ -1447,7 +1475,7 @@ Informacje: Komunikaty o pominięciu Włączenie tej opcji może spowodować problemy z odtwarzaniem filmów. Pominięto wstępnie załadowany bufor. - Przezroczystość nakładki prędkości odtwarzania musi wynosić między 0 a 8.0. Przywrócono domyślną wartość. + Przezroczystość nakładki prędkości odtwarzania musi wynosić między 0 a 8.0. Wartość nakładki prędkości odtwarzania między 0, a 8. Wartość nakładki prędkości odtwarzania "Oszukuje wersję aplikacji do starszej wersji. @@ -1481,10 +1509,13 @@ Wysoka jakość może być odblokowana na niektórych filmach, które wymagają "Włączenie tego ustawienia może poprawić żywotność baterii i naprawić zacinanie się filmów. Kodek AVC (H.264) obsługuje maksymalnie rozdzielczość 1080p, a odtwarzanie filmów wykorzystuje więcej danych internetowych niż VP9 i AV1." - • Brakuje menu od ścieżki dźwiękowej - • Brakuje menu od ścieżki dźwiękowej + "• Brakuje menu od ścieżki dźwiękowej" + "• Brakuje menu od ścieżki dźwiękowej +• Stabilna głośność jest niedostępna" "• Filmy kinowe lub płatne filmy mogą się nie odtwarzać -• Transmisje na żywo rozpoczynają się od początku" +• Transmisje na żywo rozpoczynają się od początku +• Filmy mogą kończyć się o 1 sekundę wcześniej +• Kodek opus jest niedostępny" Efekty uboczne oszukiwania • Filmy mogą się nie odtwarzać Ukryta @@ -1507,7 +1538,7 @@ Kodek AVC (H.264) obsługuje maksymalnie rozdzielczość 1080p, a odtwarzanie fi Minimalna długość przesunięcia Widoczność tła nakładki przesuwania Widoczność tła przesuwania - Rozmiar obszaru przesuwania nie może być większy niż 50. Przywrócono domyślną wartość. + Rozmiar obszaru przesuwania nie może być większy niż 50. Procentowa wartość obszaru ekranu, gdzie można przesuwać.\n\nNotka: Zmieni to także rozmiar obszaru ekranu dla gestu podwójnego kliknięcia, aby przewinąć film. Rozmiar obszaru przesuwania Rozmiar tekstu nakładki przesuwania @@ -1530,6 +1561,10 @@ Dodatkowo, reklamy nie będą już blokowane w Shortsach. Jeśli opcja nie przynosi skutku, spróbuj przełączyć się na tryb incognito." Domyślny + RVX Music + %s nie jest zainstalowany. Proszę go zainstalować. + Nazwa pakietu zainstalowanego RVX Music + Nazwa pakietu RVX Music • Historia oglądania nie działa "• Stosuje się do ustawień historii oglądania konta Google • Historia oglądania może nie działać przy używaniu DNS lub VPN" diff --git a/src/main/resources/youtube/translations/pt-rBR/missing_strings.xml b/src/main/resources/youtube/translations/pt-rBR/missing_strings.xml index 26b7e32ef..4334aeca9 100644 --- a/src/main/resources/youtube/translations/pt-rBR/missing_strings.xml +++ b/src/main/resources/youtube/translations/pt-rBR/missing_strings.xml @@ -2,28 +2,21 @@ Don\'t show again Courses / Learning - Playables Package name of your installed external downloader app, such as NewPipe or YTDLnis, on long press. Long press video downloader package name Displays the optimization dialog for GMSCore at each application startup. Show optimization dialog for GMSCore - "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. - -Limitations: -• Shorts cannot be hidden. -• Videos with 0 views are not filtered." - About view count filtering - Videos in home feed are not filtered. - Videos in home feed are filtered. - Hide home videos by views - Search results are not filtered. - Search results are filtered. - Hide search results by views - Videos in subscriptions feed are not filtered. - Videos in subscriptions feed are filtered. - Hide subscription videos by views + Save music button is shown. + Save music button is hidden. + Hide Save music button + Stickers are shown. + Stickers are hidden. + Hide stickers MMT Blue MMT Green + MMT Orange + MMT Pink + MMT Turquoise MMT Yellow Revancify Yellow Vanced Black diff --git a/src/main/resources/youtube/translations/pt-rBR/strings.xml b/src/main/resources/youtube/translations/pt-rBR/strings.xml index cc2ad1991..a28066e59 100644 --- a/src/main/resources/youtube/translations/pt-rBR/strings.xml +++ b/src/main/resources/youtube/translations/pt-rBR/strings.xml @@ -22,6 +22,7 @@ Se ativado, os URLs dos vídeos serão enviados ao servidor API e nenhum outro d Toque aqui para saber mais sobre o DeArrow." DeArrow + URL da API DeArrow inválida. A URL do ponto final do cache de miniaturas DeArrow. DeArrow API endpoint Notificação flutuante não exibida se Derow não estiver disponível. @@ -89,8 +90,12 @@ Toque aqui para saber mais sobre o DeArrow." Inscrições Em alta Assistir mais tarde - Página inicial inválida, redefinindo para o padrão. Alterar a página inicial + A página inicial muda apenas uma vez. + "Página inicial sempre muda. + +Limitação: O botão voltar na barra de ferramentas pode não funcionar." + Alterar tipo de página inicial Cabeçalhos genéricos estão ativados. O cabeçalho premium está ativado. Alterar cabeçalho do YouTube @@ -187,6 +192,9 @@ Limitação: esta configuração pode não se aplicar a vídeos que não incluem As rolagens números são animadas. As rolagens números não são animadas. Desativar animações de rolagem de números + A animação da fonte está ativada acima do botão Curtir. + A animação da fonte está desativada acima do botão Curtir. + Desativar animação do botão Curtir "Desativar o 'Reproduzindo na velocidade 2x' enquanto segurar. Nota: @@ -304,6 +312,7 @@ Estes caracteres variam dependendo do seu idioma. A descrição do vídeo é expandida automaticamente. Expandir descrição do vídeo Você deseja continuar? + Redefinir para os valores padrão. Reinicie para carregar o layout normalmente Atualizar e reiniciar Falha ao exportar configurações. @@ -570,6 +579,9 @@ Palavras com letras maiúsculas no meio devem ser inseridas com maiúsculas (ou Os painéis de filmes serão exibidos. Os painéis de filmes estão ocultos. Ocultar painel de filmes + A barra de navegação será exibida. + A barra de navegação está oculta. + Ocultar barra de navegação O botão de criação será exibido. O botão de criação está oculto. Ocultar botão de criação @@ -732,6 +744,12 @@ Palavras com letras maiúsculas no meio devem ser inseridas com maiúsculas (ou A sobreposição de vídeo relacionado será exibida. A sobreposição de vídeo relacionado está oculta. Ocultar sobreposição de vídeo relacionado + Os vídeos relacionados serão exibidos. + Os vídeos relacionados estão ocultos. + Ocultar vídeos relacionados + "Esta configuração limita o número máximo de layouts que podem ser carregados na tela do reprodutor. + +Se o layout da tela do reprodutor mudar devido a alterações no lado do servidor, layouts não intencionais podem ficar ocultos na tela do reprodutor." O botão remix será exibido. O botão remix está oculto. Ocultar botão remix @@ -796,6 +814,9 @@ Legendas" O rótulo de link de vídeo será exibido. O rótulo de link de vídeo está oculto. Ocultar rótulo completo do link do vídeo + O botão de tela verde será exibido. + O botão de tela verde está oculto. + Ocultar botão de tela verde Os painéis de informação serão exibidos. Os painéis de informação estão ocultos. Ocultar painéis de informações @@ -829,9 +850,6 @@ Legendas" O botão remix será exibido. O botão remix está oculto. Ocultar botão remix - Salvar música na lista de reprodução será exibida. - Salvar música na lista de reprodução está oculta. - Ocultar botão salvar música na lista de reprodução O botão de sugestões de pesquisa será exibido. O botão de sugestões de pesquisa está oculto. Ocultar botão de sugestões de pesquisa @@ -938,15 +956,28 @@ A reprodução automática pode ser alterada nas configurações do YouTube: As seções de transcrição serão exibidas. As seções de transcrição estão ocultas. Ocultar seções de transcrição + "Ocultar vídeos com a etiqueta PRÓXIMO. + +Nota: Ativar isso também oculta o botão Notificar-me." + Ocultar PRÓXIMO vídeo Os anúncios de vídeo serão exibidos. Os anúncios de vídeo estão ocultos. Ocultar anúncios de vídeo - Vídeos com duração maior que este número serão ocultados. - Maior que a duração - Vídeos com duração menor que este número serão ocultados. - Menor que a duração - Ocultar vídeos com duração menor ou maior que.\n\nProblema conhecido: não ocultará vídeos nos vídeos relacionados no reprodutor, ao invés disso ocultará a marcação de tempo. - Ocultar vídeos baseado na duração + "Início / Inscrições / Resultados de pesquisa são filtrados para ocultar vídeos com visualização menor ou maior que um número especificado. + +Limitações: +• Shorts não podem ser ocultos. +• Vídeos com 0 visualizações não são filtrados." + Sobre a filtragem da contagem de visualizações + Os vídeos no feed de início não são filtrados. + Os vídeos no feed de início são filtrados. + Ocultar vídeos no feed de início por visualizações + Os resultados da pesquisa não são filtrados. + Os resultados da pesquisa são filtrados. + Ocultar resultados de pesquisa por visualizações + Os vídeos no feed de inscrições não são filtrados. + Os vídeos no feed de inscrições são filtrados. + Ocultar vídeos no feed de inscrições por visualizações Oculte vídeos recomendados com menos de um determinado número de visualizações. Ocultar vídeos recomendados por visualizações Vídeos com visualizações maiores que este número serão ocultados. @@ -1041,13 +1072,18 @@ Toque e segure para abrir a caixa de diálogo de configuração da lista branca. O botão de download de vídeo nativo abre o download nativo do aplicativo. O botão de download de vídeo nativo abre seu aplicativo de download externo. Substituir o botão de download de vídeo + O YouTube Music é necessário para substituir a ação do botão. Toque aqui para baixar o YouTube Music. + Pré-requisito + O botão do YouTube Music abre o aplicativo nativo. + O botão do YouTube Music abre o RVX Music. + Substituir botão do YouTube Music Excluído Incluído Normal Botões de ação Configurações adicionais Animação / Feedback - Filtro de duração + Botão de download Sinalizadores experimentais Restrições de imagem por região Importar / Exportar como arquivo @@ -1059,6 +1095,7 @@ Toque e segure para abrir a caixa de diálogo de configuração da lista branca. Ações rápidas Vídeo recomendado Painel de shorts + Ações sugeridas Ferramenta usada Filtro por contagem de visualização Ocultar ou mostrar elementos no menu de contas e na aba Você. @@ -1089,13 +1126,15 @@ Toque e segure para abrir a caixa de diálogo de configuração da lista branca. Geral Desativar ou ativar o retorno tátil. Retorno tátil + Substitui a ação de clique dos botões do aplicativo. + Botões hook Importar ou exportar configurações. Importar / Exportar configurações Alterar o estilo do reprodutor minimizado no aplicativo. Mini reprodutor Diversos - Ocultar ou mostrar componentes da seção de navegação. - Botões de navegação + Ocultar ou mostrar componentes da seção de navegação. + Barra de Navegação Informações sobre as modificações aplicadas. Informações do patch Oculte ou mostre botões em vídeos. @@ -1131,6 +1170,7 @@ Toque e segure para abrir a caixa de diálogo de configuração da lista branca. Após cerca de 20 segundos de buffer, muda para um codec diferente." Rejeitar resposta do codec AV1 do software O processo de fallback causa cerca de 20 segundos de buffer. + Desvio As alterações de velocidade de reprodução só se aplicam ao vídeo atual. As alterações de velocidade de reprodução aplicam-se a todos os vídeos. Lembrar alterações na velocidade de reprodução @@ -1392,6 +1432,9 @@ Limitação: Dislikes pode não aparecer no modo incógnito." Margem inferior do painel meta deve estar entre 0-64. Voltar aos valores padrão. Configure o espaçamento da barra de busca para o painel meta, entre 0-64. Margem inferior do painel meta + A porcentagem de altura deve estar entre 0-100 (%). + Configura a porcentagem de altura do espaço vazio esquerdo quando a barra de navegação está oculta, entre 0 e 100 (%). + Porcentagem de altura do espaço vazio Pressione e segure a marcação de tempo para alterar o status de repetição do Shorts. Ação de toque longo na marcação de tempo "Exibe a seção de título do vídeo em tela cheia. @@ -1445,8 +1488,8 @@ A alta qualidade pode ser desbloqueada em alguns vídeos que exigem dimensões e "Ativar isto pode melhorar a duração da bateria e corrigir travamentos na reprodução. AVC (H. 64) tem uma resolução máxima de 1080p, e a reprodução de vídeo usará mais dados de internet do que VP9 ou AV1." - • O menu de faixa de áudio está faltando. - • O menu de faixa de áudio está faltando. + "• O menu de faixa de áudio está faltando." + "• O menu de faixa de áudio está faltando." "• Filmes ou vídeos pagos podem não reproduzir." Efeitos colaterais da falsificação • O vídeo pode não reproduzir. @@ -1493,6 +1536,10 @@ Além disso, os anúncios não serão mais bloqueados no Shorts. Se essa configuração não surtir efeito, tente alternar para o modo anônimo." Padrão + RVX Music + %s não está instalado. Por favor, instale-o. + Nome do pacote do RVX Music instalado. + Nome do pacote do RVX Music • O histórico de exibição não funciona. "• Segue as configurações do histórico de exibição da conta do Google. • O histórico de exibição pode não funcionar devido ao DNS ou à VPN." diff --git a/src/main/resources/youtube/translations/ru-rRU/missing_strings.xml b/src/main/resources/youtube/translations/ru-rRU/missing_strings.xml index 0511088d7..606e146ff 100644 --- a/src/main/resources/youtube/translations/ru-rRU/missing_strings.xml +++ b/src/main/resources/youtube/translations/ru-rRU/missing_strings.xml @@ -1,23 +1,25 @@ + Fountain animation is enabled above the Like button. + Fountain animation is disabled above the Like button. + Disable Like button animation Package name of your installed external downloader app, such as NewPipe or YTDLnis, on long press. Long press video downloader package name - "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. - -Limitations: -• Shorts cannot be hidden. -• Videos with 0 views are not filtered." - About view count filtering - Videos in home feed are not filtered. - Videos in home feed are filtered. - Hide home videos by views - Search results are not filtered. - Search results are filtered. - Hide search results by views - Videos in subscriptions feed are not filtered. - Videos in subscriptions feed are filtered. - Hide subscription videos by views + Green screen button is shown. + Green screen button is hidden. + Hide Green screen button + Save music button is shown. + Save music button is hidden. + Hide Save music button + Stickers are shown. + Stickers are hidden. + Hide stickers + MMT Orange + MMT Pink + MMT Turquoise Xisr Yellow + Suggested actions + Offset Adjust: Mark Start and End Time for segment Verify the Segment Edit the Segment diff --git a/src/main/resources/youtube/translations/ru-rRU/strings.xml b/src/main/resources/youtube/translations/ru-rRU/strings.xml index 6d8e8dd34..7b3514941 100644 --- a/src/main/resources/youtube/translations/ru-rRU/strings.xml +++ b/src/main/resources/youtube/translations/ru-rRU/strings.xml @@ -23,6 +23,7 @@ Нажмите здесь, чтобы узнать больше о DeArrow." О \"DeArrow\" + Неверный URL API для миниатюр DeArrow. URL кэша миниатюр DeArrow. DeArrow API Уведомление при недоступности DeArrow API отключено. @@ -86,15 +87,17 @@ Трансляции Фильмы Музыка - Игротека Поиск Shorts Спорт Подписки В тренде Смотреть позже - Недопустимая начальная страница, сброс по умолчанию. Начальная страница + Начальная страница изменится один раз. + "Начальная страница постоянно изменяется. +Ограничение: Кнопка возврат может не работать." + Тип начальной страницы Включен обычный логотип. Включен логотип Premium. Логотип YouTube @@ -309,6 +312,7 @@ Описание видео автоматически развернуто. Развернуть описание видео Подтверждаете действие? + К значениям по умолчанию. Перезапустить для правильной загрузки интерфейса? Перезапустить для применения? Не удалось экспортировать настройки. @@ -581,6 +585,9 @@ Shorts Секции фильмов отображены. Секции фильмов скрыты. Секции фильмов + Панель навигации отображена. + Панель навигации скрыта. + Панель навигации Кнопка \"Создать\" отображена. Кнопка \"Создать\" скрыта. Кнопка \"Создать\" @@ -743,6 +750,12 @@ Shorts Предложение о похожих видео отображено. Предложение о похожих видео скрыто. Предложение о похожих видео + Похожие видео отображены. + Похожие видео скрыты. + Похожие видео + "Этот параметр ограничивает максимальное количество макетов, которые могут быть загружены на экране плеера. + +Если макет экрана проигрывателя меняется из-за изменений на стороне сервера, незапланированные макеты могут быть скрыты на экране плеера." Кнопка \"Ремикс\" отображена. Кнопка \"Ремикс\" скрыта. Кнопка \"Ремикс\" @@ -845,9 +858,6 @@ Shorts Кнопка \"Ремикс\" отображена. Кнопка \"Ремикс\" скрыта. Кнопка \"Ремикс\" - Кнопка \"Сохранить звук в плейлист\" отображена. - Кнопка \"Сохранить звук в плейлист\" скрыта. - Кнопка \"Сохранить звук в плейлист\" Кнопка \"Подсказки поиска\" отображена. Кнопка \"Подсказки поиска\" скрыта. Кнопка \"Подсказки поиска\" @@ -955,15 +965,27 @@ Shorts Секция \"Расшифровка видео\" отображена. Секция \"Расшифровка видео\" скрыта. Секция \"Расшифровка видео\" + "Скрывает видео с меткой \"подготовленное\" к воспроизведению. +Примечание: Также скроется кнопка \"Уведомить\"." + Подготовленное видео Реклама в видео отображена. Реклама в видео скрыта. Реклама в видео - Видео с большей продолжительностью будут скрыты. - Продолжительность больше указанной - Видео с меньшей продолжительностью будут скрыты. - Продолжительность меньше указанной - Скрывает видео с продолжительностью меньше или больше заданной. - Скрыть видео по продолжительности + "Главная / Подписки / Результаты поиска, фильтруются, чтобы скрыть видео с просмотрами отличающиеся от введенного числа. + +Ограничения: +• Shorts нельзя скрыть. +• Видео без просмотров не обрабатываются." + О фильтре подсчета просмотров + Фильтр видео в \"Главная\", по просмотрам, отключен. + Фильтр видео в \"Главная\", по просмотрам, включен. + Фильтр видео в \"Главная\" по просмотрам + Фильтр результатов поиска, по просмотрам, отключен. + Фильтр результатов поиска, по просмотрам, включен. + Фильтр результатов поиска по просмотрам + Фильтр видео в подписках, по просмотрам, отключен. + Фильтр видео в подписках, по просмотрам, включен. + Фильтр видео в подписках по просмотрам Скрывает рекомендованные видео с заданным количеством просмотров. Скрыть рекомендованные видео по количеству просмотров Видео с большим количеством просмотров будут скрыты. @@ -1073,13 +1095,19 @@ Shorts Кнопка \"Скачать\" использует внутренний загрузчик. Кнопка \"Скачать\" использует внешний загрузчик. Действие кнопки \"Скачать\" для видео + Для переопределения кнопки требуется YouTube Music. +Нажмите здесь, чтобы загрузить YouTube Music. + Обязательное условие + Кнопка YouTube Music открывает встроенное приложение. + Кнопка YouTube Music открывает RVX Music. + Переопределить кнопку YouTube Music Не применён Применён Обычная Кнопки действий Дополнительные настройки Анимация / Обратная связь - Фильтр по продолжительности + Кнопка \"Скачать\" Экспериментальные опции Ограничения изображений по региону Импорт/экспорт в виде файла @@ -1121,13 +1149,15 @@ Shorts Основные настройки Отключить или включить виброотклик по событиям. Виброотклик + Переопределяет действие нажатия кнопок в приложении. + Настройки действий кнопок Настройки импорта/экспорта. Импорт/экспорт настроек Стиль мини-плеера. Мини-плеер Разное - Настройки кнопок навигации. - Кнопки навигации + Настроить компоненты панели навигации. + Панель навигации Информация о примененных патчах. Информация о патчах Скрыть или показать кнопки в видео. @@ -1426,6 +1456,9 @@ Shorts Отступ от шкалы воспроизведения до \"мета\" панели. Диапазон от 0 до 64. Нижнее поле отступа \"мета\" панели + Высота должна быть от 0 до 100 (%). + Настраивает высоту отступа, когда панель навигации скрыта, от 0 до 100 (%). + Процент высоты отступа Нажать и удерживать метку времени - изменить статус повтора Shorts. Длительное нажатие метки времени "Показывает секцию заголовка видео в полноэкранном режиме. @@ -1480,8 +1513,8 @@ Shorts "Включение - может улучшить время работы батареи и исправить задержки воспроизведения. AVC (H.264) имеет максимальное разрешение 1080p, и будет использовать больше интернет данных, чем VP9 или AV1." - • Меню \"Звуковая дорожка\" не доступно. - • Меню \"Звуковая дорожка\" VR не доступно. + "• Меню \"Звуковая дорожка\" не доступно." + "• Меню \"Звуковая дорожка\" VR не доступно." "• Фильмы или платные видео могут не проигрываться." Эффекты от подмены • Видео может не воспроизводиться. @@ -1529,6 +1562,10 @@ AVC (H.264) имеет максимальное разрешение 1080p, и Если эта настройка не вступила в силу, попробуйте перейти в режим инкогнито." По умолчанию + RVX Music + %s не установлен. Установите его. + Название пакета установленной RVX Music. + Имя пакета RVX Music • История просмотра не работает. "• Статус истории просмотров обычный. • История просмотров может не работать с DNS или VPN." diff --git a/src/main/resources/youtube/translations/tr-rTR/missing_strings.xml b/src/main/resources/youtube/translations/tr-rTR/missing_strings.xml index bf7c53888..319b071fe 100644 --- a/src/main/resources/youtube/translations/tr-rTR/missing_strings.xml +++ b/src/main/resources/youtube/translations/tr-rTR/missing_strings.xml @@ -1,11 +1,16 @@ Don\'t show again + Invalid DeArrow API URL. In-app share sheet is used. System share sheet is used. Change share sheet Courses / Learning - Playables + Start page changes only once. + "Start page always changes. + +Limitation: Back button on the toolbar may not work." + Change start page type "Auto switch mix playlists is enabled when autoplay is turned on. Autoplay can be changed in YouTube settings: @@ -18,13 +23,17 @@ Settings → Autoplay → Autoplay next video" Limitation: This setting may not apply to videos that do not include the 'Listen on YouTube Music' banner." Disable playback speed for music + Fountain animation is enabled above the Like button. + Fountain animation is disabled above the Like button. + Disable Like button animation VP9 codec is enabled. "VP9 codec is disabled. • Maximum resolution is 1080p. • Video playback will use more internet data than VP9. -• To get HDR playback, HDR video still uses the VP9 codec." +• VP9 codec is still used for HDR video." Disable VP9 codec + Reset to default values. Package name of your installed external downloader app, such as YTDLnis. Package name of your installed external downloader app, such as NewPipe or YTDLnis, on long press. Long press video downloader package name @@ -38,24 +47,46 @@ Limitation: This setting may not apply to videos that do not include the 'Listen Add quotes to use keyword: %s. Keyword has conflicting declarations: %s. Keyword is too short and requires quotes: %s. + Navigation bar is shown. + Navigation bar is hidden. + Hide navigation bar + Related videos are shown. + Related videos are hidden. + Hide related videos + "This setting limits the maximum number of layouts that can be loaded on the player screen. + +If the layout of the player screen changes due to server-side changes, unintended layouts may be hidden on the player screen." Disabled comments button or with label \"0\" is shown. Disabled comments button or with label \"0\" is hidden. Hide disabled comments button "Floating buttons like 'Use this sound' are shown in the Shorts channel tab." "Floating buttons like 'Use this sound' are hidden in the Shorts channel tab." + Green screen button is shown. + Green screen button is hidden. + Hide Green screen button Location button is shown. Location button is hidden. Hide location button + Save music button is shown. + Save music button is hidden. + Hide Save music button Search suggestions button is shown. Search suggestions button is hidden. Hide search suggestions button Shopping button is shown. + Stickers are shown. + Stickers are hidden. + Hide stickers Use template button is shown. Use template button is hidden. Hide Use template button Use this sound button is shown. Use this sound button is hidden. Hide Use this sound button + "Hide videos with UPCOMING label. + +Note: Enabling this also hides the Notify me button." + Hide UPCOMING video "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. Limitations: @@ -73,6 +104,9 @@ Limitations: Hide subscription videos by views MMT Blue MMT Green + MMT Orange + MMT Pink + MMT Turquoise MMT Yellow Revancify Yellow Vanced Black @@ -81,8 +115,20 @@ Limitations: If shown, the native playlist download button opens the native in-app downloader. Native playlist download button is always shown, and in public playlists, it opens your external downloader. Native video download button opens the native in-app downloader. + YouTube Music is required to override button action. Tap here to download YouTube Music. + Prerequisite + YouTube Music button opens the native app. + YouTube Music button opens the RVX Music. + Override YouTube Music button + Download button + Suggested actions + Overrides the click action of in-app buttons. + Hook buttons + Hide or show navigation bar section components. + Navigation bar Spoof the streaming data to prevent playback issues. Spoof streaming data + Offset A toast will not be shown when changing the default playback speed. A toast will be shown when changing the default playback speed. Show a toast @@ -97,16 +143,23 @@ Limitations: Publish Created Segment Rewind by Specified Time (Default: 150ms) Tap here to view your segments. + Height percentage must be between 0-100 (%). + Configure the height percentage of the empty space left when the navigation bar is hidden, between 0 and 100 (%). + Height percentage of empty space iOS video codec is AVC (H.264), VP9, or AV1. iOS video codec is AVC (H.264). Force iOS AVC (H.264) "Enabling this might improve battery life and fix playback stuttering. AVC (H.264) has a maximum resolution of 1080p, and video playback will use more internet data than VP9 or AV1." - • Audio track menu is missing. - • Audio track menu is missing. + "• Audio track menu is missing. +• Stable volume is not available." + "• Audio track menu is missing. +• Stable volume is not available." "• Movies or paid videos may not play. -• Livestreams start from the beginning." +• Livestreams start from the beginning. +• Videos may end 1 second early. +• No opus audio codec." Spoofing side effects • Video may not play. Client used to fetch streaming data is hidden in Stats for nerds. @@ -130,6 +183,10 @@ Note: Enabling this also forcibly hides video ads." Also, ads will no longer be blocked in Shorts. If this setting do not take effect, try switching to Incognito mode." + RVX Music + %s is not installed. Please install it. + Package name of installed RVX Music. + RVX Music package name "• Follows the watch history settings of Google account. • Watch history may not work due to DNS or VPN." • Follows the watch history settings of Google account. diff --git a/src/main/resources/youtube/translations/tr-rTR/strings.xml b/src/main/resources/youtube/translations/tr-rTR/strings.xml index 3b5d4add2..24ceebe08 100644 --- a/src/main/resources/youtube/translations/tr-rTR/strings.xml +++ b/src/main/resources/youtube/translations/tr-rTR/strings.xml @@ -84,7 +84,6 @@ DeArrow hakkında daha fazla bilgi edinmek için buraya dokunun." Abonelikler Trendler Daha sonra izlenecekler - Başlangıç sayfası geçersiz, varsayılana dönülüyor. Başlangıç ​​sayfasını değiştir Genel başlıklar etkin. Premium başlık etkin. @@ -779,9 +778,6 @@ Altyazılar" \"Remix\" butonu gösteriliyor. \"Remix\" butonu gizleniyor. Remix düğmesini gizle - Sesi oynatma listesine kaydetme butonu gösteriliyor. - Sesi oynatma listesine kaydetme butonu gizleniyor - Sesi oynatma listesine kaydetme butonunu gizle \"Paylaş\" butonu gösteriliyor. \"Paylaş\" butonu gizleniyor. Paylaş butonunu gizle @@ -881,12 +877,6 @@ Otomatik oynatma YouTube ayarlarından değiştirilebilir: Video reklamları gösteriliyor Video reklamları gizleniyor Video reklamlarını gizle - Süresi bu sayıdan daha uzun olan videolar gizlenecektir. - Bu süreden daha uzun - Süresi bu sayıdan daha kısa olan videolar gizlenecektir. - Bu süreden daha kısa - Süresi daha kısa veya daha uzun olan videoları gizleyin.\n\nBilinen problem: Oynatıcı ile bağlantılı videoları gizlemez, bunun yerine zaman damgasını gizler. - Süresine göre videoları gizleyin Belirtilen görüntüleme sayısından daha az olan önerilen videoları gizleyin.\n\nBilinen sorun: 0 izleme alan videolar filtrelenmez. Önerilen videoları izlenmeye göre gizle Görüntüleme sayısı bu sayıdan fazla olan videolar gizlenecektir. @@ -983,7 +973,6 @@ Beyaz liste ayarı iletişim kutusunu açmak için dokunun ve basılı tutun.Eylem düğmeleri Ek ayarlar Animasyon / geri bildirim - Süre filtresi Deneysel Parametreler Resim bölgesi kısıtlamaları İçe / Dışa dosya olarak aktar @@ -1030,8 +1019,6 @@ Beyaz liste ayarı iletişim kutusunu açmak için dokunun ve basılı tutun.Uygulama içi simge durumuna küçültülmüş oynatıcının stilini değiştirin. Miniplayer Diğer Ayarlar - Gezinme çubuğu bölümü bileşenlerini gizleyin veya gösterin. - Navigasyon tuşları Uygulanmış Yamalar Hakkında Bilgi. Yama Bilgileri Videolardaki düğmeleri gizle veya göster. diff --git a/src/main/resources/youtube/translations/uk-rUA/missing_strings.xml b/src/main/resources/youtube/translations/uk-rUA/missing_strings.xml index d22a1f7f3..f82015e55 100644 --- a/src/main/resources/youtube/translations/uk-rUA/missing_strings.xml +++ b/src/main/resources/youtube/translations/uk-rUA/missing_strings.xml @@ -1,18 +1,6 @@ - "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. - -Limitations: -• Shorts cannot be hidden. -• Videos with 0 views are not filtered." - About view count filtering - Videos in home feed are not filtered. - Videos in home feed are filtered. - Hide home videos by views - Search results are not filtered. - Search results are filtered. - Hide search results by views - Videos in subscriptions feed are not filtered. - Videos in subscriptions feed are filtered. - Hide subscription videos by views + MMT Orange + MMT Pink + MMT Turquoise diff --git a/src/main/resources/youtube/translations/uk-rUA/strings.xml b/src/main/resources/youtube/translations/uk-rUA/strings.xml index fef40e440..87e85dbbb 100644 --- a/src/main/resources/youtube/translations/uk-rUA/strings.xml +++ b/src/main/resources/youtube/translations/uk-rUA/strings.xml @@ -15,6 +15,7 @@ Натисніть тут, щоб дізнатися більше про DeArrow." DeArrow + Некоректна URL API DeArrow. URL кінцевої точки кешу мініатюр DeArrow Кінцева точка API DeArrow Тост не показується, якщо DeArrow не доступний. @@ -77,15 +78,18 @@ Наживо Фільми Музика - Ігрова кімната Пошук YouTube Shorts Спорт Підписки Тенденції Переглянути пізніше - Недійсна початкова сторінка, скидається на стандартну. Змінити початкову сторінку + Початкова сторінка змінюється лише один раз. + "Початкова сторінка змінюється завжди. + +Застереження: Кнопка Назад на панелі інструментів не працює." + Тип зміни початкової сторінки Звичний заголовок увімкнено. Заголовок Premium увімкнено. Змінити заголовок YouTube @@ -98,11 +102,11 @@ Використовується висувне меню старого стилю. Використовується специфічний діалог. Тип меню користувацької швидкості відтворення - Користувацькі швидкості повинні бути менше ніж %s Використовуються типові значення. - Неправильні користувацькі швидкості відтворення. Використовуються типові значення. + Користувацькі швидкості повинні бути менше ніж %sx. + Неправильні користувацькі швидкості відтворення. Додати або змінити доступні швидкості відтворення Редагувати користувацькі швидкості відтворення - Непрозорість затемнення плеєра має бути в межах 0-100. Скинуто. + Непрозорість затемнення плеєра має бути в межах 0-100. Значення непрозорості в межах 0-100, де 0 це прозорий Користувацька непрозорість затемнення плеєра Введіть hex код кольору смуги прогресу. @@ -182,6 +186,9 @@ Лічильники анімовані. Лічильники не анімовані. Вимкнути анімації лічильників + Фонтанну анімацію увімкнено над кнопкою Подобається. + Фонтанну анімацію вимкнено над кнопкою Подобається. + Вимкнути анімацію кнопки Подобається "Вимикається 'Відтворення зі швидкістю 2x' під час утримання Зауваження: @@ -201,7 +208,7 @@ • Максимальна роздільна здатність - 1080p. • Відтворення відео використовуватиме більше інтернет даних ніж VP9. -• Щоб отримати відтворювання HDR, HDR відео використовує кодек VP9." +• Кодек VP9 все ще використовується для HDR відео." Вимкнути кодек VP9 Смугу прогресу Каїр вимкнено. "Смугу прогресу Каїр увімкнено. @@ -301,6 +308,7 @@ Опис відео розгортається автоматично. Розгортати опис відео Бажаєте продовжити? + Скинуто. Перезапустіть, щоб нормально завантажився макет Поновити й перезапустити Не вдалося експортувати налаштування. @@ -574,6 +582,9 @@ Полиці фільмів показується. Полиці фільмів приховано. Приховати полицю фільмів + Панель навігації показується. + Панель навігації приховано. + Приховати панель навігації Кнопку Створити показується. Кнопку Створити приховано. Приховати кнопку Створити @@ -735,6 +746,12 @@ Секцію \'Більше відео\' у контейнері швидких дій та пов\'язаних відео показується. Секцію \'Більше відео\' у контейнері швидких дій та пов\'язаних відео приховано. Приховати пов’язані відео + Пов\'язані відео показується. + Пов\'язані відео приховано. + Приховати пов’язані відео + "Це налаштування обмежує максимальну кількість, які можуть вантажитися на екран плеєра. + +Якщо екран плеєра змінюється через зміни на стороні сервера, можуть бути приховані ненавмисно на екрані плеєра." Кнопку Ремікс показується. Кнопку Ремікс приховано. Приховати кнопку Ремікс @@ -799,6 +816,9 @@ Мітку посилання відео показується. Мітку посилання відео приховано. Приховати мітку посилання на повне відео + Кнопку Зелений екран показується. + Кнопку Зелений екран приховано. + Приховати кнопку Зелений екран Інформаційні панелі показується. Інформаційні панелі приховано. Приховати інформаційні панелі @@ -832,9 +852,9 @@ Кнопку Ремікс показується. Кнопку Ремікс приховано. Приховати кнопку Ремікс - Зберегти звук в списку відтворення показується. - Зберегти звук в списку відтворення приховано. - Приховати кнопку Зберегти звук в списку відтворення + Кнопку Зберегти звук показується. + Кнопку Зберегти звук приховано. + Приховати кнопку Зберегти звук Кнопку пропозицій пошуку показується. Кнопку пропозицій пошуку приховано. Приховати кнопку пропозицій пошуку @@ -869,6 +889,9 @@ Мітку метаданих показується. Мітку метаданих приховано. Приховати мітку метаданих звуку + Стікери показується. + Стікери приховано. + Приховати стікери Кнопку Підписатися показується. Кнопку Підписатися приховано. Приховати кнопку Підписатися @@ -944,15 +967,28 @@ Секції Текст відео показується. Секції Текст відео приховано. Приховати секції Текст відео + "Приховати відео з міткою НЕЗАБАРОМ. + +Примітка: Увімкнення також приховає кнопку Сповістити." + Приховати відео НЕЗАБАРОМ Відеорекламу показується. Відеорекламу приховано. Приховати відеорекламу - Відео з тривалістю більше цього числа приховуватимуться. - Довші за тривалістю - Відео з тривалістю менше цього числа приховуватимуться. - Коротші за тривалістю - Приховати відео з меншою або більшою тривалістю.\n\nВідома проблема: Не приховуватимуться пов\'язані відео у плеєрі, натомість приховуватиметься мітку часу. - Приховати відео за тривалістю + "Головна/Підписки/Результати пошуку фільтрується, щоб приховати відео з переглядами менше або більше вказаної кількості. + +Застереження: +• YouTube Shorts неможливо приховати. +• Відео з 0 переглядів не фільтруються." + Про фільтрацію за переглядами + Відео у головній стрічці не фільтруються. + Відео у головній стрічці фільтруються. + Приховати відео на головній за переглядами + Результати пошуку не фільтрується. + Результати пошуку фільтрується. + Приховати результати пошуку за переглядами + Відео у стрічці підписок не фільтруються. + Відео у стрічці підписок фільтруються. + Приховати відео підписок за переглядами Приховати рекомендовані відео з меншою за вказану кількість переглядів.\n\nВідома проблема: Відео з 0 переглядами не фільтруються. Приховати рекомендовані відео за переглядами Відео з більше ніж ця кількість переглядів приховуватимуться. @@ -1012,7 +1048,7 @@ Підтексти показується. Підтексти приховано. Приховати підтексти - Непрозорість затемнення мініплеєра має бути в межах 0-100. Скинуто. + Непрозорість затемнення мініплеєра має бути в межах 0-100. Значення непрозорості в межах 0-100, де 0 це прозоро. Непрозорість затемнення Оригінал @@ -1053,13 +1089,18 @@ Кнопка завантаження відео відкриває вбудований завантажувач. Кнопка завантаження відео відкриває зовнішній завантажувач. Перевизначити кнопку завантаження відео + Для перевизначення дії кнопки потрібно YouTube Music. Натисніть тут, щоб завантажити YouTube Music. + Передумова + Кнопка YouTube Music відкриває стандартний додаток. + Кнопка YouTube Music відкриває RVX Music. + Перевизначити кнопку YouTube Music Виключено Включено Стандартна Кнопки дії Додаткові налаштування Анімація / Відгук - Фільтр тривалості + Кнопка завантаження Експериментальні опції Регіональні обмеження зображень Імпорт / Експорт як файл @@ -1071,6 +1112,7 @@ Швидкі дії Рекомендовані відео Полиця Shorts + Пропоновані дії Використано інструменти Фільтр за кількістю переглядів Приховувати чи показувати елементи меню облікового запису і вкладки Ви. @@ -1101,13 +1143,15 @@ Загальне Вимкнути чи увімкнути вібрацію. Вібрація + Перевизначення дії натискання кнопок додатка. + Заміна кнопок Імпортувати або експортувати налаштування. Імпорт/Експорт налаштувань Зміна стилю мінімізованого плеєра в додатку. Мініплеєр Різне - Приховувати чи показувати секцію компонентів панелі навігації. - Кнопки панелі навігації + Приховувати чи показувати секцію компонентів панелі навігації. + Панель навігації Інформація про застосовані патчі. Інформація про патчі Приховувати чи показувати кнопки у відео. @@ -1136,13 +1180,14 @@ Відео Змінити налаштування пов\'язані з історією перегляду. Історія перегляду - Верхній відступ швидких дій повинен бути в межах 0-32. Скинуто. + Верхній відступ швидких дій повинен бути в межах 0-32. Налаштуйте відстань від панелі прогресу до контейнера швидких дій, діапазон 0-32. Верхній відступ швидких дій "Примусово відкидається відповідь програмного кодека AV1. Приблизно через 20 секунд буферизації перемикається на інший кодек." Відкинути відповідь програмного кодека AV1 Процес спричиняє приблизно 20 секунд буферизації. + Зміщення Зміни швидкості відтворення застосовуються лише до поточного відео. Зміни швидкості відтворення застосовуються до всіх відео. Запам\'ятовувати зміни швидкості відтворення @@ -1407,9 +1452,12 @@ Серце (Тоноване) Прихована Анімація подвійного натискання - Нижній відступ метапанелі повинен бути в межах 0-64. Скинуто. + Нижній відступ метапанелі повинен бути в межах 0-64. Налаштуйте відстань від панелі прогресу до метапанелі, діапазон 0-64. Нижній відступ метапанелі + Відсоток висоти повинен бути в межах 0-100 (%). + Налаштуйте відсоток висоти порожнього простору, що залишається, коли приховано панель навігації, між 0 і 100 (%). + Відсоток висоти порожнього простору Натисніть і утримуйте мітку часу для зміни станів повторення Shorts. Дія довго натискання на мітку часу "Показується секцію назви відео в повноекранному режимі. @@ -1429,7 +1477,7 @@ Показувати тост, коли пропущено Вмикання цього налаштування може спричинити проблеми відтворення відео. Пропущено перед вантажений буфер - Значення накладання швидкості повинно бути в межах 0-8.0. Скинуто. + Значення накладання швидкості повинно бути в межах 0-8.0. Значення накладання швидкості в межах 0-8.0. Значення накладання швидкості "Підміна версії клієнта на стару версію @@ -1463,10 +1511,14 @@ "Увімкнення може зменшити споживання акумулятора та усунути затинання при відтворенні. AVC (H.264) має максимальну роздільну здатність 1080p, а для відтворення відео використовується більше інтернет-даних, ніж VP9 або AV1." - • Меню звукової доріжки відсутнє. - • Меню звукової доріжки відсутнє. + "• Меню звукової доріжки відсутнє. +• Стабілізація гучності недоступна." + "• Меню звукової доріжки відсутнє. +• Стабілізація гучності недоступна." "• Фільми чи платні відео можуть не відтворюватися. -• Прямі трансляції починаються з початку." +• Прямі трансляції починаються з початку. +• Відео можуть закінчуватися на 1 секунду раніше. +• Немає аудіокодека opus." Побічні ефекти імітування • Відео може не відтворюватися. Клієнт, що використовується для отримання даних трансляції приховано у Статистика для сисадмінів. @@ -1489,7 +1541,7 @@ AVC (H.264) має максимальну роздільну здатність Поріг величини жесту Видимість фону панелі при жесті Видимість фону при жесті - Розмір площі для проведення не може бути більшим ніж 50. Скинуто. + Розмір площі для проведення не може бути більшим ніж 50. Відсоток площі екрана для проведення.\n\nЗауваження: це також змінить розмір площі екрану для жесту перемотування подвійним натисканням. Розмір екрана накладки проведення Розмір шрифту в панелі при жесті @@ -1512,6 +1564,10 @@ AVC (H.264) має максимальну роздільну здатність Якщо це налаштування не діє, спробуйте перемкнути Анонімний режим." Стандартна + RVX Music + %s не встановлено. Будь ласка, встановіть. + Назва пакету встановленого RVX Music. + Назва пакету RVX Music • Історію перегляду заблоковано. "• Дотримується налаштувань історії перегляду облікового запису Google. • Історія перегляду може не працювати через DNS або VPN." diff --git a/src/main/resources/youtube/translations/vi-rVN/missing_strings.xml b/src/main/resources/youtube/translations/vi-rVN/missing_strings.xml index 26b7e32ef..a0dadfc3c 100644 --- a/src/main/resources/youtube/translations/vi-rVN/missing_strings.xml +++ b/src/main/resources/youtube/translations/vi-rVN/missing_strings.xml @@ -2,28 +2,15 @@ Don\'t show again Courses / Learning - Playables Package name of your installed external downloader app, such as NewPipe or YTDLnis, on long press. Long press video downloader package name Displays the optimization dialog for GMSCore at each application startup. Show optimization dialog for GMSCore - "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. - -Limitations: -• Shorts cannot be hidden. -• Videos with 0 views are not filtered." - About view count filtering - Videos in home feed are not filtered. - Videos in home feed are filtered. - Hide home videos by views - Search results are not filtered. - Search results are filtered. - Hide search results by views - Videos in subscriptions feed are not filtered. - Videos in subscriptions feed are filtered. - Hide subscription videos by views MMT Blue MMT Green + MMT Orange + MMT Pink + MMT Turquoise MMT Yellow Revancify Yellow Vanced Black diff --git a/src/main/resources/youtube/translations/vi-rVN/strings.xml b/src/main/resources/youtube/translations/vi-rVN/strings.xml index a9a77f2a0..921084967 100644 --- a/src/main/resources/youtube/translations/vi-rVN/strings.xml +++ b/src/main/resources/youtube/translations/vi-rVN/strings.xml @@ -22,6 +22,7 @@ Nếu được bật, chỉ có URL video được gửi đến máy chủ API, Nhấn vào đây để tìm hiểu thêm về DeArrow." Giới thiệu về DeArrow + URL của API DeArrow không hợp lệ. URL điểm cuối của bộ nhớ đệm hình thu nhỏ DeArrow. Không thay đổi URL này trừ khi bạn biết mình đang làm gì. Điểm cuối API DeArrow Thông báo ngắn nếu API DeArrow không khả dụng đã tắt. @@ -72,7 +73,7 @@ Nhấn vào đây để tìm hiểu thêm về DeArrow." Mặc định Dừng Lặp lại - Thay đổi trạng thái lặp lại của trình phát Shorts + Thay đổi trạng thái lặp lại video ngắn Duyệt kênh Mặc định Khám phá @@ -89,8 +90,12 @@ Nhấn vào đây để tìm hiểu thêm về DeArrow." Kênh đăng ký Thịnh hành Xem sau - Trang khởi động không hợp lệ. Đã đặt lại về mặc định. Thay đổi trang khởi động + Trang khởi động chỉ thay đổi một lần. + "Trang khởi động sẽ liên tục thay đổi. + +Hạn chế: Nút Quay lại trên thanh công cụ có thể không hoạt động được." + Thay đổi trang khởi động Tiêu đề Youtube mặc định. Tiêu đề Premium được kích hoạt. Thay đổi tiêu đề YouTube @@ -101,13 +106,13 @@ Nhấn vào đây để tìm hiểu thêm về DeArrow." Bộ lọc tuỳ chỉnh Bộ lọc tuỳ chỉnh không hợp lệ: %s. Mục tốc độ phát kiểu cũ được sử dụng. - Hộp thoại tùy chỉnh được sử dụng. + Mục tốc độ phát dạng hộp thoại được sử dụng. Kiểu mục tốc độ phát tùy chỉnh - Tốc độ tùy chỉnh phải nhỏ hơn %sx. Đã đặt lại về giá trị mặc định. - Tốc độ phát tùy chỉnh không hợp lệ. Đã đặt lại về giá trị mặc định. + Tốc độ tùy chỉnh phải nhỏ hơn %sx. + Tốc độ phát tùy chỉnh không hợp lệ. Thêm hoặc thay đổi tốc độ phát lại có sẵn. Chỉnh sửa tốc độ phát - Độ mờ của lớp phủ trình phát phải nằm trong khoảng 0 - 100. Đã đặt lại về mặc định. + Độ mờ của lớp phủ trình phát phải nằm trong khoảng 0 - 100. Giá trị độ mờ của lớp phủ trình phát trong khoảng từ 0 đến 100, trong đó 0 là trong suốt. Độ mờ lớp phủ trình phát Nhập mã màu hex của thanh tiến trình video mà bạn muốn thay đổi. @@ -183,10 +188,13 @@ Hạn chế: Cài đặt này có thể sẽ không áp dụng cho các video kh Vô hiệu hoá giao thức QUIC Trinh phát Shorts sẽ tiếp tục khi ứng dụng khởi chạy. Trinh phát Shorts sẽ không tiếp tục khi ứng dụng khởi chạy. - Tắt tiếp tục trình phát Shorts + Tắt tính năng tiếp tục trình phát Shorts Đã bật Hoạt ảnh số cuộn. Đã tắt Hoạt ảnh số cuộn. Tắt hoạt ảnh số cuộn + Đã kích hoạt hiệu ứng phun nước trên nút Thích. + Đã vô hiệu hoá hiệu ứng phun nước trên nút Thích. + Vô hiệu hoá hiệu ứng nút Thích "Tắt tính năng Nhấn và giữ trong trình phát để xem ở tốc độ nhanh gấp 2 lần. • Bật tuỳ chọn này sẽ khôi phục tính năng Trượt để tua của bố cục cũ. @@ -203,9 +211,9 @@ Hạn chế: Cài đặt này có thể sẽ không áp dụng cho các video kh Bộ giải mã VP9 đã được kích hoạt. "Bộ giải mã VP9 đã bị vô hiệu hoá. -• Độ phân giải tối đa sẽ là 1080p. +• Độ phân giải tối đa là 1080p. • Việc phát video sẽ sử dụng nhiều dữ liệu di động hơn so với VP9. -• Để có thể phát video HDR, bộ giải mã VP9 vẫn sẽ được sử dụng." +• Bộ giải mã VP9 vẫn được sử dụng cho video HDR." Vô hiệu hoá bộ giải mã VP9 Thanh điều hướng kiểu Cairo đã được vô hiệu hoá. "Thanh điều hướng kiểu Cairo đã được bật @@ -252,11 +260,11 @@ Hạn chế: Chủ đề Cairo cũng được áp dụng cho dấu chấm thông Chạm thanh tiến trình video để tua đã tắt. Chạm thanh tiến trình video để tua đã bật. Chạm thanh tiến trình để tua - Mốc thời gian đã vô hiệu hóa. - "Mốc thời gian được bật. + Đã vô hiệu hoá Mốc thời gian. + "Đã kích hoạt Mốc thời gian. Hạn chế: -• Cài đặt này không chỉ bật Mốc thời gian mà còn cho phép ẩn giao diện người dùng bằng cách nhấn vào nền trình phát. +• Cài đặt này không chỉ kích hoạt Mốc thời gian mà còn cho phép ẩn giao diện người dùng bằng cách nhấn vào nền trình phát. • Vì đây là tính năng đang trong giai đoạn phát triển của Google nên bố cục có thể bị hỏng." Bật Mốc thời gian Cử chỉ vuốt Độ sáng đã tắt. @@ -288,7 +296,7 @@ Hạn chế: "Bật thanh tìm kiếm rộng trên thẻ Bạn. Tuỳ chọn này sẽ ẩn nút Cài đặt trên thẻ Bạn. Để truy cập phần Cài đặt, vui lòng làm theo các bước sau: -Thẻ Bạn → Xem kênh → Trình đơn → Cài đặt" +Thẻ Bạn → Xem kênh → Trình đơn → Cài đặt." Thanh tìm kiếm rộng trên thẻ Bạn Thanh tìm kiếm rộng đã tắt. Thanh tìm kiếm rộng đã bật. @@ -304,6 +312,7 @@ Mở rộng mô tả video có thể không hoạt động nếu bạn lưu chu Mô tả video được mở rộng tự động. Mở rộng mô tả video Bạn có muốn tiếp tục không? + Đặt lại về giá trị mặc định. Vui lòng khởi động lại ứng dụng trong lần đầu khởi chạy để các tính năng hoạt động bình thường Làm mới và khởi động lại Xuất cài đặt thất bại. @@ -329,9 +338,9 @@ Mở rộng mô tả video có thể không hoạt động nếu bạn lưu chu Cảnh báo %s chưa được cài đặt. Hãy cài đặt và thử lại. Nhập tên gói ứng dụng trình tải xuống đã cài đặt trên thiết bị của bạn, chẳng hạn như YTDLnis. - Tên gói ứng dụng trình tải xuống danh sách phát + Tên gói trình tải xuống danh sách phát Nhập tên gói ứng dụng trình tải xuống đã cài đặt trên thiết bị của bạn, chẳng hạn như NewPipe hoặc YTDLnis. - Tên gói ứng dụng trình tải xuống video + Tên gói trình tải xuống video "Video sẽ chuyển sang chế độ toàn màn hình trong các trường hợp sau: • Khi video bắt đầu. @@ -380,7 +389,7 @@ Một số thành phần có thể không bị ẩn." Các đường liên kết ở đầu hồ sơ kênh được hiển thị. Các đường liên kết ở đầu hồ sơ kênh đã ẩn. Ẩn đường liên kết trên hồ sơ kênh - "Shorts + "Video ngắn Danh sách phát Cửa hàng" Nhập tên các thẻ trên kênh mà bạn muốn lọc được phân cách bằng dòng. @@ -400,9 +409,9 @@ Cửa hàng" Nút Tạo đoạn video được hiển thị. Nút Tạo đoạn video đã ẩn. Ẩn nút Tạo đoạn video - Nút Tạo tạo Short được hiển thị. - Nút Tạo video Short đã ẩn. - Ẩn nút Tạo video Short + Đã hiện nút Tạo video ngắn. + Đã ẩn nút Tạo video ngắn. + Ẩn nút Tạo video ngắn Nút Cảm ơn được hiển thị. Nút Cảm ơn đã ẩn. Ẩn nút Cảm ơn @@ -445,13 +454,13 @@ Cửa hàng" Bảng giới thiệu mở rộng được hiển thị bên dưới video. Bảng giới thiệu mở rộng đã ẩn bên dưới video. Ẩn bảng giới thiệu mở rộng - Kệ Hiện thêm đã được hiển thị. - Kệ Hiện thêm đã bị ẩn. - Ẩn kệ Hiện thêm + Kệ Mở rộng đã hiển thị. + Kệ Mở rộng đã ẩn. + Ẩn kệ Mở rộng Nút Phụ đề được hiển thị. Nút Phụ đề đã ẩn. Ẩn nút Phụ đề - Nhập tên các mục thành phần của trình đơn tuỳ chọn mà bạn muốn lọc được phân cách bằng dòng. + Nhập tên các mục thành phần của mục tuỳ chọn mà bạn muốn lọc được phân cách bằng dòng. Chỉnh sửa bộ lọc Bộ lọc trình đơn tuỳ chọn trên bảng tin đã tắt. Bộ lọc trình đơn tuỳ chọn trên bảng tin đã bật. @@ -515,17 +524,17 @@ Hạn chế: Hình ảnh của bài đăng cộng đồng ở chế độ toàn "Nội dung khớp với từ khoá bạn đã đặt sẽ bị ẩn trên thẻ Trang chủ/Kênh đăng ký và kết quả tìm kiếm. Hạn chế: -• Video Shorts không bị ẩn theo tên kênh. +• Video ngắn sẽ không bị ẩn theo tên kênh. • Một số thành phần giao diện người dùng có thể không bị ẩn. • Tìm kiếm từ khoá có thể không cho kết quả nào." Giới thiệu về lọc từ khoá Việc đặt từ/cụm từ cần lọc trong dấu ngoặc kép sẽ ngăn chặn các kết quả chỉ trùng một phần với tiêu đề video và tên kênh.<br><br>Ví dụ,<br><b>\"ai\"</b> sẽ ẩn video: <b>How does AI work?</b><br>nhưng sẽ không ẩn: <b>What does fair use mean?</b> Khớp toàn bộ từ - Bình luận không lọc theo từ khoá đã đặt. - Bình luận được lọc theo từ khoá đã đặt. + Bình luận không được lọc theo từ khoá đã đặt. + Bình luận đã được lọc theo từ khoá đã đặt. Ẩn bình luận theo từ khoá - Các Video trên thẻ Trang chủ không lọc theo từ khoá đã đặt. - Các Video trên thẻ Trang chủ được lọc theo từ khoá đã đặt. + Các Video trên thẻ Trang chủ không được lọc theo từ khoá đã đặt. + Các Video trên thẻ Trang chủ đã được lọc theo từ khoá đã đặt. Ẩn video trên thẻ Trang chủ theo từ khoá "Nhập từ hoặc cụm từ cần ẩn được phân cách bằng dòng. @@ -533,11 +542,11 @@ Từ khóa có thể là tên kênh hoặc bất kỳ văn bản nào hiển th Bộ lọc có phân biệt chữ hoa chữ thường, vì vậy bạn cần nhập chính xác định dạng để lọc (Ví dụ: iPhone, TikTok, LeBlanc)." Bộ lọc từ khoá - Kết quả tìm kiếm không lọc theo từ khoá đã đặt. - Kết quả tìm kiếm được lọc theo từ khoá đã đặt. + Kết quả tìm kiếm không được lọc theo từ khoá đã đặt. + Kết quả tìm kiếm đã được lọc theo từ khoá đã đặt. Ẩn kết quả tìm kiếm theo từ khóa - Các Video trên thẻ Kênh đăng ký không lọc theo từ khoá đã đặt. - Các Video trên thẻ Kênh đăng ký được lọc theo từ khoá đã đặt. + Các Video trên thẻ Kênh đăng ký không được lọc theo từ khoá đã đặt. + Các Video trên thẻ Kênh đăng ký đã được lọc theo từ khoá đã đặt. Ẩn video trên thẻ Kênh đăng ký theo từ khoá Từ khóa sẽ ẩn tất cả video: %s. Không thể sử dụng từ khoá: %s. @@ -573,6 +582,9 @@ Bộ lọc có phân biệt chữ hoa chữ thường, vì vậy bạn cần nh Phim và chương trình truyền hình được hiển thị. Phim và chương trình truyền hình đã ẩn. Ẩn phim và chương trình truyền hình + Thanh điều hướng đã được hiển thị. + Thanh điều hướng đã bị ẩn. + Ẩn Thanh điều hướng Nút Tạo được hiển thị. Nút Tạo đã ẩn. Ẩn nút Tạo @@ -588,8 +600,8 @@ Bộ lọc có phân biệt chữ hoa chữ thường, vì vậy bạn cần nh Nút Thông báo được hiển thị. Nút Thông báo đã ẩn. Ẩn nút Thông báo - Nút Shorts được hiển thị. - Nút Shorts đã ẩn. + Đã hiện nút Shorts. + Đã ẩn nút Shorts. Ẩn nút Shorts Nút Kênh đăng ký được hiển thị. Nút Kênh đăng ký đã ẩn. @@ -654,9 +666,9 @@ Bộ lọc có phân biệt chữ hoa chữ thường, vì vậy bạn cần nh Ghi chú cuối mục Chất lượng video hiện tại được hiển thị. Ghi chú cuối mục Chất lượng video hiện tại đã ẩn. Ẩn ghi chú cuối mục Chất lượng - Tiêu đề trình đơn Chất lượng được hiển thị. - Tiêu đề trình đơn Chất lượng đã ẩn. - Ẩn tiêu đề trình đơn Chất lượng + Tiêu đề mục Chất lượng được hiển thị. + Tiêu đề mục Chất lượng đã ẩn. + Ẩn tiêu đề mục Chất lượng Mục Báo vi phạm được hiển thị. Mục Báo vi phạm đã ẩn. Ẩn mục Báo cáo @@ -734,6 +746,12 @@ Bộ lọc có phân biệt chữ hoa chữ thường, vì vậy bạn cần nh Phần video thêm trong bảng nút thao tác nhanh và lớp phủ video liên quan đã được hiển thị. Phần video thêm trong bảng nút thao tác nhanh và lớp phủ video liên quan đã bị ẩn. Ẩn lớp phủ video liên quan + Nút Video có liên quan được hiển thị. + Các video có liên quan đã bị ẩn. + Ẩn các video có liên quan + "Cài đặt này giới hạn số lượng bố cục tối đa có thể được tải trên màn hình trình phát. + +Nếu bố cục của màn hình trình phát thay đổi do các thay đổi từ phía máy chủ, các bố cục không mong muốn có thể bị ẩn trên màn hình trình phát." Nút Remix được hiển thị. Nút Remix đã ẩn. Ẩn nút Remix @@ -774,71 +792,74 @@ Phụ đề" Nút Chia sẻ được hiển thị. Nút Chia sẻ đã ẩn. Ẩn nút Chia sẻ - Nút Mua sắm được hiển thị. - Nút Mua sắm đã ẩn. - Ẩn nút Mua sắm + Nút Cửa hàng được hiển thị. + Nút Cửa hàng đã ẩn. + Ẩn nút Cửa hàng Phần Sản phẩm được hiển thị. Phần Sản phẩm đã ẩn. Ẩn phần Sản phẩm - Thanh kênh được hiển thị. - Thanh kênh được ẩn - Ẩn thanh kênh - Nút Bình luận được hiển thị. - Nút Bình luận đã ẩn. + Đã hiện Thanh kênh. + Đã ẩn Thanh kênh. + Ẩn Thanh kênh + Đã hiện nút Bình luận. + Đã ẩn nút Bình luận. Ẩn nút Bình luận Nút Bình luận đã tắt hoặc nhãn \"0\" được hiển thị. Nút Bình luận đã tắt hoặc nhãn \"0\" đã ẩn. Ẩn nút Đóng bình luận - Nút Không thích đã được hiển thị. - Nút Không thích đã bị ẩn. + Đã hiện nút Không thích. + Đã ẩn nút Không thích. Ẩn nút Không thích - "Các nút nổi như 'Dùng bản âm thanh này' được hiển thị trong tab kênh Shorts." - "Các nút nổi như 'Dùng bản âm thanh này' bị ẩn trong tab kênh Shorts." + "Đã hiện các nút nổi như 'Dùng bản âm thanh này' trong thẻ kênh Shorts." + "Đã ẩn các nút nổi như 'Dùng bản âm thanh này' trong thẻ kênh Shorts." Ẩn nút nổi - Nhãn liên kết video được hiển thị. - Nhãn liên kết video đã ẩn. - Ẩn nhãn liên kết video toàn màn hình - Bảng thông tin được hiển thị. - Bảng thông tin đã ẩn. + Đã hiện nhãn Liên kết video. + Đã ẩn nhãn Liên kết video. + Ẩn nhãn Liên kết toàn video + Đã hiện nút Phông xanh. + Đã ẩn nút Phông xanh. + Ẩn nút Phông xanh + Đã hiện Bảng thông tin. + Đã ẩn Bảng thông tin. Ẩn Bảng thông tin - Nút Tham gia được hiển thị. - Nút Tham gia được ẩn. + Đã hiện nút Tham gia. + Đã ẩn nút Tham gia. Ẩn nút Tham gia - Nút Thích được hiển thị. - Nút Thích được ẩn. + Đã hiện nút Thích. + Đã ẩn nút Thích. Ẩn nút Thích - Tiêu đề Trò chuyện trực tiếp được hiển thị.\n\nNút Quay lại trong tiêu đề sẽ không bị ẩn. - Tiêu đề Trò chuyện trực tiếp đã ẩn.\n\nNút Quay lại trong tiêu đề sẽ không bị ẩn. + Đã hiện tiêu đề Trò chuyện trực tiếp.\n\nNút Quay lại trong tiêu đề sẽ không bị ẩn. + Đã ẩn tiêu đề Trò chuyện trực tiếp.\n\nNút Quay lại trong tiêu đề sẽ không bị ẩn. Ẩn tiêu đề Trò chuyện trực tiếp - Nút Vị trí đã hiển thị. - Nút Vị trí đã ẩn. + Đã hiện nút Vị trí. + Đã ẩn nút Vị trí. Ẩn nút Vị trí - Thanh điều hướng được hiển thị. - Thanh điều hướng đã ẩn. + Đã hiện Thanh điều hướng. + Đã ẩn Thanh điều hướng. Ẩn Thanh điều hướng - Nhãn quảng cáo được tài trợ được hiển thị. - Nhãn quảng cáo được tài trợ đã ẩn. + Đã hiện Nhãn quảng cáo được tài trợ. + Đã ẩn Nhãn quảng cáo được tài trợ. Ẩn nhãn quảng cáo được tài trợ - Tiêu đề tạm dừng đã được hiển thị. - Tiêu đề tạm dừng đã bị ẩn. + Đã hiện Tiêu đề tạm dừng. + Đã ẩn Tiêu đề tạm dừng. Ẩn tiêu đề tạm dừng - Các nút phủ lên khi tạm dừng được hiển thị. - Các nút phủ lên khi tạm dừng được ẩn. + Đã hiện các nút phủ lên khi tạm dừng. + Đã ẩn các nút phủ lên khi tạm dừng. Ẩn các nút phủ lên khi tạm dừng - Nền nút được hiển thị. - Nền nút bị ẩn. + Đã hiển thị nền của nút. + Đã ẩn nền của nút. Ẩn nền các nút Phát & Tạm dừng - Nút Remix được hiển thị. - Nút Remix đã ẩn. - Ẩn nút Remix - Nút lưu vào danh sách phát được hiển thị. - Nút lưu vào danh sách phát đã ẩn. - Ẩn nút Lưu vào danh sách phát - Nút Gợi ý tìm kiếm đã hiển thị. - Nút Gợi ý tìm kiếm đã ẩn. + Đã hiện nút Phối lại. + Đã ẩn nút Phối lại. + Ẩn nút Phối lại + Đã hiện nút lưu nhạc. + Đã ẩn nút Lưu nhạc. + Ẩn nút Lưu nhạc + Đã hiện nút Gợi ý tìm kiếm. + Đã ẩn nút Gợi ý tìm kiếm. Ẩn nút Gợi ý tìm kiếm - Nút Chia sẻ được hiển thị. - Nút Chia sẻ đã ẩn . + Đã hiện nút Chia sẻ. + Đã ẩn nút Chia sẻ. Ẩn nút Chia sẻ Hiển thị trong phần Nhật ký xem. Ẩn trong phần Nhật ký xem. @@ -856,42 +877,45 @@ Phụ đề" Hạn chế: Tiêu đề chính thức trong kết quả tìm kiếm sẽ được ẩn." Ẩn kệ Shorts - Nút Mua sắm được hiển thị. - Nút Mua sắm đã ẩn. - Ẩn nút Mua sắm - Nút Mua sắm đã hiển thị. - Nút Mua sắm đã ẩn. + Đã hiện nút Cửa hàng. + Đã ẩn nút Cửa hàng. + Nút Cửa hàng + Đã hiện nút Mua sắm. + Đã ẩn nút Mua sắm. Ẩn nút Mua sắm - Nút Âm thanh được hiển thị. - Nút Âm thanh đã ẩn. + Đã hiện nút Âm thanh. + Đã ẩn nút Âm thanh. Nút Âm thanh - Nhãn siêu dữ liệu được hiển thị. - Nhãn siêu dữ liệu đã ẩn. - Ẩn nhãn siêu dữ liệu âm thanh - Nút Đăng ký được hiển thị. - Nút Đăng ký đã ẩn. + Đã hiện nhãn Siêu dữ liệu. + Đã ẩn nhãn Siêu dữ liệu. + Ẩn nhãn Siêu dữ liệu âm thanh + Đã hiện nhãn dán. + Đã ẩn nhãn dán. + Ẩn nhãn dán + Đã hiện nút Đăng ký. + Đã ẩn nút Đăng ký. Ẩn nút Đăng ký - Nút Cảm ơn được hiển thị. - Nút Cảm ơn đã ẩn. - Ẩn nút Cảm ơn - Sản phẩm gắn thẻ được hiển thị. - Sản phẩm được gắn thẻ đã ẩn. + Đã hiện nút Super Thanks. + Đã ẩn nút Super Thanks. + Ẩn nút Super Thanks + Đã hiện Sản phẩm được gắn thẻ. + Đã ẩn Sản phẩm được gắn thẻ. Ẩn sản phẩm được gắn thẻ - Thanh công cụ được hiển thị. - Thanh công cụ đã ẩn. + Đã hiện Thanh công cụ. + Đã ẩn Thanh công cụ. Ẩn thanh công cụ - Nút Thịnh hành đã hiển thị. - Nút Thịnh hành đã ẩn. + Đã hiện nút Thịnh hành. + Đã ẩn nút Thịnh hành. Ẩn nút Thịnh hành - Nút Sử dụng mẫu đã hiển thị. - Nút Sử dụng mẫu đã ẩn. + Đã hiện nút Sử dụng mẫu. + Ẩn nút Sử dụng mẫu. Ẩn nút Sử dụng mẫu - Nút \'Dùng bản âm thanh này\' đã hiển thị. - Nút \'Dùng bản âm thanh này\' đã ẩn. + Đã hiện nút \'Dùng bản âm thanh này\'. + Đã ẩn nút \'Dùng bản âm thanh này\'. Ẩn nút \'Dùng bản âm thanh này\' - Tiêu đề được hiển thị. - Tiêu đề đã ẩn. - Ẩn tiêu đề video + Đã hiện Tiêu đề. + Đã ẩn Tiêu đề. + Ẩn Tiêu đề video Nút Hiện thêm được hiển thị. Nút Hiện thêm đã ẩn. Ẩn nút Hiện thêm @@ -943,15 +967,28 @@ Cài đặt → Tự động phát → Tự động phát video tiếp theo."Phần Bản chép lời được hiển thị. Phần Bản chép lời đã ẩn. Ẩn phần Bản chép lời + "Ẩn các video có nhãn \"SẮP DIỄN RA\". + +Lưu ý: Việc bật tính năng này cũng sẽ ẩn nút Thông báo cho tôi." + Ẩn video SẮP DIỄN RA Quảng cáo dạng video được hiển thị. Quảng cáo dạng video đã ẩn. Ẩn quảng cáo dạng video - Nhập thời lượng. Video có thời lượng dài hơn mức này sẽ bị ẩn. - Dài hơn - Nhập thời lượng. Video có thời lượng ngắn hơn mức này sẽ bị ẩn. - Ngắn hơn - Ẩn các video có thời lượng ngắn hơn hoặc dài hơn thời lượng bạn đã đặt.\n\nSự cố đã biết: Tính năng này sẽ không ẩn video có liên quan trong trình phát mà chỉ ẩn mốc thời gian. - Ẩn video theo thời lượng + "Các Video có số lượt xem ít hoặc nhiều hơn con số bạn đã đặt sẽ bị ẩn trên thẻ Trang chủ/Kênh đăng ký/Kết quả tìm kiếm. + +Hạn chế: +• Không ẩn đối với Video ngắn. +• Các Video có 0 lượt xem cũng không bị lọc." + Về việc lọc theo số lượt xem + Các Video trên thẻ Trang chủ không được lọc theo số lượt xem đã đặt. + Các Video trên thẻ Trang chủ đã được lọc theo số lượt xem đã đặt. + Ẩn video trên thẻ Trang chủ theo số lượt xem + Kết quả tìm kiếm không được lọc theo số lượt xem đã đặt. + Kết quả tìm kiếm đã được lọc theo số lượt xem đã đặt. + Ẩn kết quả tìm kiếm theo lượt xem + Các Video trên thẻ Kênh đăng ký không được lọc theo số lượt xem đã đặt. + Các Video trên thẻ Kênh đăng ký đã được lọc theo số lượt xem đã đặt. + Ẩn video trên thẻ Kênh đăng ký theo số lượt xem Ẩn các video đề xuất có số lượt xem ít hơn số lượt xem bạn đã đặt.\n\nSự cố đã biết: Các video chưa có lượt xem nào sẽ không bị lọc. Ẩn video được đề xuất theo số lượt xem Nhập số lượt xem. Video có số lượt xem cao hơn mức này sẽ bị ẩn. @@ -1004,7 +1041,7 @@ Cài đặt → Tự động phát → Tự động phát video tiếp theo."Văn bản được hiển thị. Văn bản đã ẩn. Ẩn văn bản - Độ mờ của lớp phủ trình phát thu nhỏ phải nằm trong khoảng 0 - 100. Đã đặt lại về mặc định. + Độ mờ của lớp phủ trình phát thu nhỏ phải nằm trong khoảng 0 - 100. Giá trị độ mờ của lớp phủ trình phát thu nhỏ trong khoảng từ 0 đến 100, trong đó 0 là trong suốt. Độ mờ lớp phủ Gốc @@ -1039,19 +1076,24 @@ Nhấn và giữ để hoàn tác." \"Nhấn để mở hộp thoại Danh sách trắng. Nhấn và giữ để mở hộp thoại cài đặt Danh sách trắng. Hiển thị nút Danh sách trắng - Nếu được hiển thị, nút tải xuống danh sách phát sẽ mở trình tải xuống gốc trong ứng dụng. + Nếu được hiển thị, nút tải xuống danh sách phát sẽ mở trình tải xuống tích hợp sẵn trong ứng dụng. Nút tải xuống danh sách phát sẽ luôn được hiển thị, và khi thao tác sẽ mở trình tải xuống bên ngoài đối với các danh sách phát công khai. Ghi đè nút tải xuống danh sách phát - Nút tải xuống video sẽ mở trình tải xuống gốc trong ứng dụng. + Nút tải xuống video sẽ mở trình tải xuống tích hợp sẵn trong ứng dụng. Nút tải xuống video sẽ mở trình tải xuống bên ngoài của bạn. Ghi đè nút tải xuống video + Cần phải có YouTube Music để ghi đè hành động của nút. Nhấn vào đây để tải YouTube Music. + Điều kiện tiên quyết + Nút Youtube Music sẽ mở ứng dụng YT Music. + Nút Youtube Music sẽ mở ứng dụng RVX Music. + Ghi đè nút Youtube Music Không bao gồm Đã bao gồm Bình thường Nút hành động Cài đặt bổ sung Hoạt ảnh / Phản hồi - Bộ lọc thời lượng + Nút tải xuống Tính năng thử nghiệm Hạn chế về hình ảnh do khu vực Nhập/Xuất dưới dạng tập tin @@ -1063,6 +1105,7 @@ Nhấn và giữ để mở hộp thoại cài đặt Danh sách trắng.Thao tác nhanh Video được đề xuất Kệ Shorts + Hành động đề xuất Công cụ được sử dụng Bộ lọc số lượt xem Ẩn hoặc hiển thị các thành phần của trình đơn Tài khoản và thẻ Bạn. @@ -1085,7 +1128,7 @@ Nhấn và giữ để mở hộp thoại cài đặt Danh sách trắng.Bài đăng cộng đồng Ẩn các thành phần không mong muốn bằng bộ lọc tuỳ chỉnh. Bộ lọc tuỳ chỉnh - Ẩn hoặc hiển thị thành phần của trình đơn tuỳ chọn trong bảng tin. + Ẩn hoặc hiển thị thành phần của trình đơn tuỳ chọn trên bảng tin. Trình đơn tuỳ chọn Bảng tin Ẩn hoặc thay đổi các thành phần liên quan đến toàn màn hình. @@ -1093,13 +1136,15 @@ Nhấn và giữ để mở hộp thoại cài đặt Danh sách trắng.Tổng quan Tắt hoặc bật phản hồi xúc giác. Phản hồi xúc giác + Ghi đè thao tác nhấn của các nút trong ứng dụng. + Điều chỉnh nút Nhập hoặc xuất cài đặt. Nhập/Xuất cài đặt Thay đổi kiểu trình phát thu nhỏ trong ứng dụng. Trình phát thu nhỏ Cài đặt khác - Ẩn hoặc hiển thị các nút thành phần trên thanh điều hướng. - Thanh điều hướng + Ẩn hoặc hiển thị các thành phần trong phần thanh điều hướng. + Thanh điều hướng Thông tin về các bản vá đã được áp dụng. Thông tin bản vá Ẩn hoặc hiển thị các nút trong video. @@ -1123,18 +1168,19 @@ Nhấn và giữ để mở hộp thoại cài đặt Danh sách trắng.Thanh công cụ Ẩn hoặc hiển thị các thành phần mô tả video. Mô tả video - Ẩn video theo từ khoá hoặc lượt xem. + Ẩn video theo từ khoá hoặc số lượt xem. Bộ lọc video Video Thay đổi cài đặt liên quan đến Nhật ký xem. Nhật ký xem - Lề trên bảng nút thao tác nhanh phải nằm trong khoảng 0 - 32. Đã đặt lại về mặc định. + Lề trên bảng nút thao tác nhanh phải nằm trong khoảng 0 - 32. Giá trị khoảng cách từ thanh tiến trình đến bảng nút thao tác nhanh trong khoảng từ 0 đến 32. Lề trên bảng nút thao tác nhanh "Buộc từ chối phản hồi của bộ giải mã phần mềm AV1. Một bộ giải mã khác sẽ được áp dụng sau khoảng 20 giây tải bộ đệm." Từ chối phản hồi của bộ giải mã phần mềm AV1 Quá trình dự phòng sẽ tạo ra khoảng 20 giây tải bộ đệm. + Độ lệch Thay đổi tốc độ phát chỉ áp dụng cho video hiện tại. Thay đổi tốc độ phát áp dụng cho tất cả video. Lưu thay đổi tốc độ phát @@ -1156,9 +1202,9 @@ Tuỳ chọn này chỉ tự động chấp nhận hộp thoại cảnh báo, kh Đóng hộp thoại cảnh báo trước khi xem Thay thế bộ giải mã phần mềm AV1 bằng bộ giải mã VP9. Thay thế bộ giải mã phần mềm AV1 - Tên người dùng của kênh đã được sử dụng. - Tên kênh đã được sử dụng. - Thay thế tên người dùng của kênh + Đang hiển thị tên người dùng (@username). + Đang hiển thị tên kênh. + Thay đổi tên người dùng Shorts Nhấn để hiển thị thời gian còn lại. Nhấn để mở mục Tốc độ phát hoặc Chất lượng video. Thay thế hành động của mốc thời gian @@ -1250,7 +1296,7 @@ Hạn chế: Lượt không thích có thể không hiển thị nếu người Thời lượng video trừ đi tất cả các phân đoạn, được hiển thị trong dấu ngoặc đơn bên cạnh thời lượng video đầy đủ. Id người dùng riêng tư của bạn ID người dùng riêng tư phải dài ít nhất 30 ký tự. - Bạn nên giữ bí mật mã này. Nó như mật khẩu vậy, do đó không nên chia sẻ với người khác. Nếu ai đó có mã này, họ có thể giả mạo bạn. + Mã Id này giống như mật khẩu của bạn vậy, do đó không nên chia sẻ với bất kỳ ai. Nếu ai đó có được nó, họ có thể mạo danh bạn. Đã đọc Hãy đọc hướng dẫn của SponsorBlock trước khi tạo phân đoạn mới. Xem ngay @@ -1388,16 +1434,19 @@ Hạn chế: Lượt không thích có thể không hiển thị nếu người Đã sao chép URL cùng mốc thời gian vào bảng nhớ tạm. Nguyên bản Thumbs up - Thumbs up (Loang màu) + Thumbs up (Cairo) Trái tim Trái tim (Đỏ) Ẩn Hoạt ảnh nhấn đúp - Lề dưới cùng của bảng meta phải nằm trong khoảng từ 0-64. Đặt lại về giá trị mặc định. - Cấu hình khoảng cách từ thanh tìm kiếm đến bảng meta, trong khoảng 0-64. + Lề dưới của bảng Meta phải nằm trong khoảng từ 0 đến 64. + Cấu hình khoảng cách từ thanh tiến trình tới bảng meta, nằm trong khoảng 0 đến 64. Lề dưới của bảng Meta - Nhấn và giữ vào Mốc thời gian để thay đổi trạng thái phát lặp lại trên Shorts. - Nhấn giữ Mốc thời gian + Chiều cao phải nằm trong khoảng từ 0 đến 100 (%). + Cấu hình chiều cao của khoảng trống còn lại khi thanh điều hướng bị ẩn, nằm trong khoảng từ 0 đến 100 (%). + Chiều cao của khoảng trống + Nhấn và giữ vào Mốc thời gian để thay đổi trạng thái phát lặp lại trên trình phát Shorts. + Thao tác nhấn giữ Mốc thời gian "Hiển thị phần tiêu đề video ở chế độ toàn màn hình. Hạn chế: Tiêu đề video sẽ biến mất khi nhấn vào." @@ -1405,7 +1454,7 @@ Hạn chế: Tiêu đề video sẽ biến mất khi nhấn vào." Bỏ qua đếm ngược tự động phát đã tắt.\nNếu tính năng Tự động phát được bật, video tiếp theo sẽ phát sau khi hết thời gian đếm ngược. Bỏ qua đếm ngược tự động phát đã bật.\nNếu tính năng Tự động phát được bật, video tiếp theo sẽ phát ngay lập tức mà không cần đếm ngược. Bỏ qua tự động đếm ngược trước khi phát - "Bỏ qua bộ đệm tải trước khi bắt đầu video để ngay lập tức áp dụng chất lượng video mặc định. + "Bỏ qua bộ đệm tải trước ở đầu video để áp dụng ngay chất lượng video mặc định. Chi tiết: • Khi video bắt đầu, sẽ có độ trễ khoảng 0,3 giây. @@ -1416,7 +1465,7 @@ Chi tiết: Hiện thông báo ngắn khi bỏ qua Việc bật cài đặt này có thể gây ra sự cố phát video. Đã bỏ qua bộ đệm tải trước. - Tốc độ phát khi nhấn và giữ phải nằm trong khoảng 0 - 8.0. Đã đặt lại về mặc định. + Tốc độ phát khi nhấn và giữ phải nằm trong khoảng 0 - 8.0. Nhập tốc độ phát khi nhấn và giữ trong khoảng từ 0 đến 8.0. Tốc độ phát khi nhấn và giữ "Giả mạo phiên bản YouTube hiện tại thành phiên bản cũ. @@ -1450,16 +1499,20 @@ Chất lượng cao có thể được mở khóa trên một số video yêu c "Bật chức năng này có thể tăng cường thời lượng pin và khắc phục tình trạng giật lag khi phát video. AVC (H.264) có độ phân giải tối đa 1080p, và phát video sẽ dùng nhiều dữ liệu di động hơn với VP9 hoặc AV1." - • Mục Bản âm thanh bị thiếu. - • Mục Bản âm thanh bị thiếu. + "• Mục Bản âm thanh bị thiếu. +• Mục 'Âm lượng ổn định' không khả dụng." + "• Mục Bản âm thanh bị thiếu. +• Mục 'Âm lượng ổn định' không khả dụng." "• Phim hoặc video trả phí có thể không phát được. -• Video phát trực tiếp sẽ khởi chạy từ đầu." +• Video phát trực tiếp sẽ khởi chạy từ đầu. +• Video có thể kết thúc sớm 1 giây. +• Không có bộ giải mã âm thanh opus." Hạn chế của việc giả mạo • Video có thể không phát được. Máy khách được sử dụng để lấy dữ liệu phát trực tiếp sẽ bị ẩn trong Thống kê chi tiết. Máy khách được sử dụng để lấy dữ liệu truyền trực tuyến sẽ được hiển thị trong Thống kê chi tiết. Hiển thị trong Thống kê chi tiết - "Dữ liệu phát trực tiếp hiện không được giả mạo. Việc phát video có thể không hoạt động bình thường." + "Chưa giả mạo dữ liệu phát trực tiếp. Phát video có thể không hoạt động bình thường." Đã giả mạo dữ liệu phát trực tiếp. Giả mạo dữ liệu phát trực tiếp Android @@ -1467,7 +1520,7 @@ AVC (H.264) có độ phân giải tối đa 1080p, và phát video sẽ dùng n Android VR iOS Máy khách mặc định - Việc tắt cài đặt này có thể gây ra sự cố phát video. + Việc tắt cài đặt này có thể gây ra sự cố khi phát video. Vuốt ở chế độ Khóa màn hình đã tắt. Cử chỉ vuốt đã bật ở chế độ Khóa màn hình. Vuốt ở chế độ Khóa màn hình @@ -1476,8 +1529,8 @@ AVC (H.264) có độ phân giải tối đa 1080p, và phát video sẽ dùng n Độ rộng ngưỡng vuốt Độ mờ của nền lớp phủ vuốt khi thực hiện cử chỉ vuốt. Độ mờ nền lớp phủ vuốt - Kích thước khu vực vuốt không được lớn hơn 50. Đã đặt lại về mặc định. - Tỉ lệ phần trăm diện tích màn hình có thể vuốt.\n\nLưu ý: Thao tác này cũng sẽ thay đổi kích thước vùng màn hình đối với cử chỉ nhấn đúp để tua. + Kích thước khu vực vuốt không được lớn hơn 50. + Phần diện tích màn hình có thể vuốt.\n\nLưu ý: Thao tác này cũng sẽ thay đổi kích thước vùng màn hình đối với cử chỉ nhấn đúp để tua. Kích thước văn bản trên lớp phủ vuốt Độ to nhỏ của văn bản được hiển thị trên lớp phủ vuốt. Kích thước văn bản trên lớp phủ vuốt @@ -1499,6 +1552,10 @@ Ngoài ra, quảng cáo sẽ không còn bị chặn trong trình phát Shorts. Nếu cài đặt này không có hiệu lực, hãy thử chuyển sang chế độ Ẩn danh." Nguyên gốc + RVX Music + Hiện %s chưa được cài đặt. Hãy cài đặt và thử lại. + Tên gói của RVX Music đã được cài đặt. + Tên gói của RVX Music • Nhật ký xem bị chặn. "• Tuân theo cài đặt Nhật ký xem của tài khoản Google. • Nhật ký xem có thể không hoạt động do DNS hoặc VPN." diff --git a/src/main/resources/youtube/translations/zh-rCN/missing_strings.xml b/src/main/resources/youtube/translations/zh-rCN/missing_strings.xml index cf0a420f0..fe55eb720 100644 --- a/src/main/resources/youtube/translations/zh-rCN/missing_strings.xml +++ b/src/main/resources/youtube/translations/zh-rCN/missing_strings.xml @@ -1,20 +1,65 @@ + Start page changes only once. + "Start page always changes. + +Limitation: Back button on the toolbar may not work." + Change start page type + Fountain animation is enabled above the Like button. + Fountain animation is disabled above the Like button. + Disable Like button animation Package name of your installed external downloader app, such as NewPipe or YTDLnis, on long press. Long press video downloader package name + Navigation bar is shown. + Navigation bar is hidden. + Hide navigation bar + Related videos are shown. + Related videos are hidden. + Hide related videos + "This setting limits the maximum number of layouts that can be loaded on the player screen. + +If the layout of the player screen changes due to server-side changes, unintended layouts may be hidden on the player screen." + Green screen button is shown. + Green screen button is hidden. + Hide Green screen button + Save music button is shown. + Save music button is hidden. + Hide Save music button + Stickers are shown. + Stickers are hidden. + Hide stickers "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. Limitations: • Shorts cannot be hidden. • Videos with 0 views are not filtered." About view count filtering - Videos in home feed are not filtered. - Videos in home feed are filtered. - Hide home videos by views Search results are not filtered. Search results are filtered. Hide search results by views Videos in subscriptions feed are not filtered. Videos in subscriptions feed are filtered. Hide subscription videos by views + MMT Orange + MMT Pink + MMT Turquoise + YouTube Music is required to override button action. Tap here to download YouTube Music. + Prerequisite + YouTube Music button opens the native app. + YouTube Music button opens the RVX Music. + Override YouTube Music button + Download button + Suggested actions + Overrides the click action of in-app buttons. + Hook buttons + Hide or show navigation bar section components. + Navigation bar + Offset + Height percentage must be between 0-100 (%). + Configure the height percentage of the empty space left when the navigation bar is hidden, between 0 and 100 (%). + Height percentage of empty space + RVX Music + %s is not installed. Please install it. + Package name of installed RVX Music. + RVX Music package name diff --git a/src/main/resources/youtube/translations/zh-rCN/strings.xml b/src/main/resources/youtube/translations/zh-rCN/strings.xml index d5335d82f..ecbbf791e 100644 --- a/src/main/resources/youtube/translations/zh-rCN/strings.xml +++ b/src/main/resources/youtube/translations/zh-rCN/strings.xml @@ -23,6 +23,7 @@ 点击此处了解更多关于 DeArrow 的信息。" 关于 DeArrow + 无效的 DeArrow API URL DeArrow 缩略图缓存端点 URL。除非您知道自己在做什么,否则请勿更改 DeArrow API 端点 如果 DeArrow 不可用,不显示 Toast @@ -85,14 +86,12 @@ 直播 电影 音乐 - 游戏 搜索 Shorts 体育 订阅 热门 稍后观看 - 起始页无效,正在重置为默认值 更改起始页 默认标题已启用 高级标题已启用 @@ -306,6 +305,7 @@ 自动展开视频描述 自动展开视频描述 你想继续吗? + 重置为默认值 重启应用以正常加载界面布局 刷新并重启 导出配置失败 @@ -833,9 +833,6 @@ 混剪按钮已显示 混剪按钮已隐藏 隐藏混剪按钮 - 保存声音到播放列表按钮已显示 - 保存声音到播放列表按钮已隐藏 - 隐藏保存声音到播放列表按钮 搜索建议按钮已显示 搜索建议按钮已隐藏 隐藏搜索建议按钮 @@ -945,15 +942,16 @@ Note: 转写文稿部分已显示 转写文稿部分已隐藏 隐藏转写文稿部分 + "隐藏带有 UPCOMING 标签的视频 + +注意:启用此选项也隐藏通知按钮" + 隐藏 UPCOMING 视频 视频广告已显示 视频广告已隐藏 隐藏视频广告 - 时长高于此数字的推荐视频将被隐藏 - 时长高于此数字 - 时长低于此数字的视频将被隐藏 - 时长低于此数字 - 隐藏时长短于或长于指定时长的视频\n\n已知问题:它不会隐藏播放器中相关视频的时间戳,而是隐藏视频时间标记 - 根据时长隐藏视频 + 首页订阅内容的关键词过滤已禁用 + 首页订阅内容的关键词过滤已启用 + 启用首页播放量过滤器 隐藏播放量低于此数字的推荐视频 播放量 播放量大于此数字的视频将被隐藏。 @@ -1060,7 +1058,6 @@ Note: 操作按钮 其他设置 动画/反馈 - 视频时长过滤器 实验性功能 图像区域限制 导入 / 导出为文件 @@ -1107,8 +1104,6 @@ Note: 更改应用最小化播放器样式 迷你播放器 杂项 - 隐藏或显示导航栏区域的组件 - 导航按钮 已应用补丁的信息 补丁信息 隐藏或显示视频中的按钮 @@ -1460,8 +1455,8 @@ Note: "启用此功能可能会改善耗电并修复播放卡顿问题 AVC (H.264) 的最大解析度为 1080p,且视频播放将使用比 VP9 或 AV1 更多的网路数据" - • 音轨菜单缺失 - • 音轨菜单缺失 + "• 音轨菜单缺失" + "• 音轨菜单缺失" "• 电影或付费视频可能无法播放" 伪装副作用 • 视频可能无法播放 diff --git a/src/main/resources/youtube/translations/zh-rTW/missing_strings.xml b/src/main/resources/youtube/translations/zh-rTW/missing_strings.xml index 0511088d7..f1f9d0bdc 100644 --- a/src/main/resources/youtube/translations/zh-rTW/missing_strings.xml +++ b/src/main/resources/youtube/translations/zh-rTW/missing_strings.xml @@ -2,21 +2,15 @@ Package name of your installed external downloader app, such as NewPipe or YTDLnis, on long press. Long press video downloader package name - "Home / Subscription / Search results are filtered to hide videos with views less or greater than a specified number. - -Limitations: -• Shorts cannot be hidden. -• Videos with 0 views are not filtered." - About view count filtering - Videos in home feed are not filtered. - Videos in home feed are filtered. - Hide home videos by views - Search results are not filtered. - Search results are filtered. - Hide search results by views - Videos in subscriptions feed are not filtered. - Videos in subscriptions feed are filtered. - Hide subscription videos by views + Save music button is shown. + Save music button is hidden. + Hide Save music button + Stickers are shown. + Stickers are hidden. + Hide stickers + MMT Orange + MMT Pink + MMT Turquoise Xisr Yellow Adjust: Mark Start and End Time for segment Verify the Segment diff --git a/src/main/resources/youtube/translations/zh-rTW/strings.xml b/src/main/resources/youtube/translations/zh-rTW/strings.xml index 2273c3dc2..1a8289540 100644 --- a/src/main/resources/youtube/translations/zh-rTW/strings.xml +++ b/src/main/resources/youtube/translations/zh-rTW/strings.xml @@ -23,6 +23,7 @@ 輕觸這裡來進一步了解關於 DeArrow 的資訊。" 關於 DeArrow + DeArrow API URL 無效。 DeArrow 縮圖快取端點網址。 縮圖快取端點的 URL 如果 DeArrow 無法使用,不顯示提示訊息 @@ -85,15 +86,18 @@ 直播 電影 音樂 - Playables 搜尋 短片 運動 訂閱 熱門 稍後觀看 - 起始頁無效,正在重設為預設值。 更改起始頁 + 起始頁僅更改一次。 + "起始頁總是改變。 + +限制:工具列上的後退按鈕可能無法運作。" + 變更起始頁類型 預設標題已啟用 高級標題已啟用 變更 YouTube 標題 @@ -191,6 +195,9 @@ 滾動動畫已啟用 滾動動畫已停用 停用滾動數字動畫 + 點讚按鈕上方的噴泉動畫已啟用。 + 點讚按鈕上方的噴泉動畫已停用。 + 停用讚按鈕動畫 "停用「按住即可將播放速度設為 2 倍」功能 注意: @@ -304,6 +311,7 @@ 自動展開影片描述 自動展開影片描述 你想繼續嗎? + 重設為預設值。 重新啟動以套用更改後的介面 重新啟動以重新整理介面 導出配置失敗 @@ -572,6 +580,9 @@ 電影庫已顯示 電影庫已隱藏 隱藏電影庫 + 導覽列已顯示。 + 導覽列已隱藏。 + 隱藏導覽列 創作按鈕已顯示 創作按鈕已隱藏 隱藏創作按鈕 @@ -733,6 +744,12 @@ 相關影片疊加層已顯示 相關影片疊加層已隱藏 隱藏相關影片疊加層 + 相關影片已顯示。 + 相關影片已隱藏。 + 隱藏相關影片 + "此設定限制播放器螢幕上可以載入佈局的最大數量。 + +如果由於伺服器端變更而導致播放器螢幕佈局發生變化,則播放器螢幕上可能會隱藏非預期的佈局。" 混剪按鈕已顯示 混剪按鈕已隱藏 隱藏混剪按鈕 @@ -797,6 +814,9 @@ 影片連結標簽已顯示 影片連結標簽已隱藏 隱藏完整影片連結標簽 + 綠幕按鈕已顯示。 + 綠幕按鈕已隱藏。 + 隱藏綠幕按鈕 訊息面板已顯示 訊息面板已隱藏 隱藏訊息面板 @@ -830,9 +850,6 @@ 混剪按鈕已顯示 混剪按鈕已隱藏 隱藏混剪按鈕 - 儲存音效到播放清單按鈕已顯示。 - 儲存音效到播放清單按鈕已隱藏。 - 隱藏儲存音效到播放清單按鈕 顯示搜尋建議按鈕。 搜尋建議按鈕已隱藏。 隱藏搜尋建議按鈕 @@ -942,15 +959,28 @@ Note: 轉寫文稿部分已顯示 轉寫文稿部分已隱藏 隱藏轉寫文稿部分 + "隱藏帶有即將推出的標籤的影片。 + +注意:啟用此功能也會隱藏「通知我」按鈕。" + 隱藏即將發布的影片 影片廣告已顯示 影片廣告已隱藏 隱藏影片廣告 - 時長高於這個值的推薦影片會被隱藏 - 時長高於這個值 - 時長小於這個值的影片會被隱藏 - 時長小於這個值 - 隱藏時長過短或過長的影片。\n\n已知問題:這不會隱藏影片播放器中的相關影片,只會隱藏影片的時間戳記。 - 根據時長隱藏影片 + "主頁/訂閱/搜尋結果將被過濾以隱藏觀看次數小於或大於指定數量的影片。 + +限制: +• 短影片無法隱藏。 +• 觀看次數為0的影片不會被曬選。" + 關於觀看次數篩選 + 首頁中的影片不會被篩選。 + 首頁中的影片已被篩選。 + 依觀看次數隱藏家庭影片 + 搜尋結果不會被篩選。 + 搜尋結果已被篩選。 + 按觀看次數隱藏搜尋結果 + 訂閱來源中的影片不會被過濾。 + 訂閱來源中的影片已被篩選。 + 按觀看次數隱藏訂閱影片 隱藏觀看次數低於這個值的推薦影片 依觀看次數隱藏推薦影片 播放量大於此數字的影片將被隱藏。 @@ -1050,13 +1080,18 @@ Note: 原生影片下載按鈕可開啟本機應用程式內下載器。 原生影片下載按鈕可開啟你的外部下載器。 覆蓋影片下載按鈕 + YouTube音樂 需要覆蓋按鈕操作。 按此下載 YouTube音樂。 + 先決條件 + YouTube音樂 按鈕可開啟本機應用程式。 + YouTube音樂 按鈕可開啟 RVX 音樂。 + 覆蓋 YouTube音樂 按鈕 排除 包括 一般 操作按鈕 其他設定 動畫 / 回饋 - 影片時長篩選器 + 下載按鈕 實驗性功能 影像區域限制 導入 / 導出為文件 @@ -1068,6 +1103,7 @@ Note: 快速操作 推薦影片 短片欄 + 建議採取的行動 使用的工具 --唐懂翻譯 觀看次數篩選器 隱藏或顯示帳戶選單和你的內容分頁中的元素。 @@ -1098,13 +1134,15 @@ Note: 一般設定 停用或啟用觸覺反饋 觸覺反饋 + 覆蓋應用程式內按鈕的點選操作。 + 掛鉤按鈕 導入或導出設定 導入/導出設定 變更應用程式內最小化播放器的樣式。 最小化播放器 其他設定 - 隱藏或顯示導航欄區域的元件 - 導航按鈕 + 隱藏或顯示導覽列部分組件。 + 導覽列 已應用補丁的訊息 補丁訊息 隱藏或顯示影片中的按鈕 @@ -1140,6 +1178,7 @@ Note: 約 20 秒的緩衝後會應用不同的編解碼器。" 拒絕軟體 AV1 編解碼器回應 切換過程會導致約 20 秒載入 + 偏移 播放速度更改僅適用於當前影片 播放速度更改適用於所有影片 記住播放速度更改 @@ -1407,6 +1446,9 @@ Note: 面板底部邊距必須介於 0-64 之間。 重設為預設值。 配置從搜尋欄到面板的間距,範圍為 0-64。 面板下邊距 + 高度百分比必須介於 0-100 (%) 之間。 + 配置隱藏導覽列時留下的空白空間的高度百分比,介於 0 到 100 (%) 之間。 + 空白空間高度百分比 按住時間戳記可變更短片重複狀態。 長按時間戳記 "在全螢幕模式下顯示影片標題部分 @@ -1460,8 +1502,8 @@ Note: "啟用此功能可能會延長電池壽命並修復播放卡頓問題。 AVC (H.264) 的最大解析度為 1080p,影片播放將比 VP9 或 AV1 使用更多的網路資料。" - • 音軌選單遺失。 - • 音軌選單遺失。 + "• 音軌選單遺失。" + "• 音軌選單遺失。" "• 電影或付費影片可能無法播放。" 偽裝副作用 • 影片可能無法播放。 @@ -1508,6 +1550,10 @@ AVC (H.264) 的最大解析度為 1080p,影片播放將比 VP9 或 AV1 使用 若此設定未生效,請嘗試切換至無痕模式。" 預設 + RVX 音樂 + %s 未安裝。 請安裝它。 + 已安裝的 RVX 音樂 套件名稱。 + RVX 音樂包名稱 • 觀看歷史記錄不起作用。 "• 遵循Google 帳戶的觀看記錄設定。 • 由於 DNS 或 VPN 的原因,觀看記錄可能無法運作。" diff --git a/src/main/resources/youtube/visual/icons/yt_alt/drawable/revanced_extended_settings_key_icon.xml b/src/main/resources/youtube/visual/icons/yt_alt/drawable/revanced_extended_settings_key_icon.xml new file mode 100644 index 000000000..d135324c6 --- /dev/null +++ b/src/main/resources/youtube/visual/icons/yt_alt/drawable/revanced_extended_settings_key_icon.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/src/main/resources/youtube/visual/shared/drawable/revanced_preference_screen_navigation_bar_icon.xml b/src/main/resources/youtube/visual/shared/drawable/revanced_preference_screen_navigation_bar_icon.xml new file mode 100644 index 000000000..dce23219f --- /dev/null +++ b/src/main/resources/youtube/visual/shared/drawable/revanced_preference_screen_navigation_bar_icon.xml @@ -0,0 +1,18 @@ + + + + + diff --git a/src/utils/remove_unused_strings.py b/src/utils/remove_unused_strings.py index 744899bac..c5750f4cf 100644 --- a/src/utils/remove_unused_strings.py +++ b/src/utils/remove_unused_strings.py @@ -16,6 +16,7 @@ ) PREFIX_TO_IGNORE = ( "revanced_icon_", + "revanced_spoof_app_version_target_entry_", "revanced_spoof_streaming_data_side_effects_", )